javascriptphpsymfonystimulusjs

Symfony with Webpack and Stimulus loading all controllers on every page


I have an issue with the setup mentioned in the title. Project is using Symfony 7.1 with Webpack encore and stimulus. I have a combination of custom.js files for individual pages and stimulus controllers. Unfortunately, all stimulus controllers are bundled into app.js and loaded on every page. Even with the /* stimulusFetch: 'lazy' */ comment.

This is a horrible thing because I have quite a few custom controllers and they are meant for individual pages, not the whole site. This increases the bundle size for no reason and some controllers are not meant for public but registered/logged in users.

How can I change this behavior and only load the controller where I need it? The current bootstrap.js is as default from Symfony:

import { startStimulusApp } from "@symfony/stimulus-bridge";

// Registers Stimulus controllers from controllers.json and in the controllers/
export const app = startStimulusApp(
  require.context(
    "@symfony/stimulus-bridge/lazy-controller-loader!./controllers",
    true,
    /\.[jt]sx?$/
  )
);

I tried loading bootstrap.js from another file than app.js but then none of the controllers load. I also tried not registering any controllers like so:

import { startStimulusApp } from "@symfony/stimulus-bridge";
const app = startStimulusApp();
export default app;

And then manually calling app.register('', ); in individual .js files, however it won't load.


Solution

  • It looks like you use modern ECMAScript version and stimulus-bridge does not recognize your code as it use ES2020 version.

    This bug is already submitted but has no solution yet.

    The problem is in the comment parsing. Stimulus-bridge tries to parse your code as ES2020, in some place it fails with parse error, don't expose any error and you think that all is fine. But it didn't parse your code successfully and stimulus doesn't know about your comment so all the controllers compiled to one file.

    You can use patch-package to fix it yourself. Just install it and follow the readme.

    So your solution would be:

    1. Install patch-package

      yarn add patch-package postinstall-postinstall
      npx json -I -f package.json -e 'this.scripts.postinstall="patch-package"'
      
    2. Fix "bug":

      sed -i '' 's/ecmaVersion: 2020/ecmaVersion: 2022/' node_modules/@symfony/stimulus-bridge/src/util/get-stimulus-comment-options.ts
      
    3. Create patch:

      yarn patch-package @symfony/stimulus-bridge
      

    After that you will not loose your fix to vendor-related files. Patch will be applied after every yarn install action. Also check that ES2022 is the right version for you and change it if needed.