How to only load css for used blocks on frontend

To get separate files for each block you’ll need to bring your own webpack config

One as simple as this should work:

const defaultConfig = require('@wordpress/scripts/config/webpack.config');

module.exports = {
    ...defaultConfig,
    entry: {
        'hero': './src/hero',
        'call-to-action': './src/callToAction',
    },
};

Ryan Welcher has an example repo and a video walk-through of its creation (that link is to the part about creating the custom webpack config).

UPDATE: It turns out it is possible to get separate bundles without a custom webpack config but (with v19.1.0 of @wordpress/scripts) it will only work if the entry points have different filenames. That is, it will fail to include a file if another has the same name. For instance, this would build but foo/index.js would be left out:

"build:custom": "wp-scripts build foo/index.js bar/index.js"

Whereas this would work as expected:

"build:custom": "wp-scripts build foo/foo.js bar/bar.js"