javascriptwebpackwebpack-4webpack-5

How to configure runtimeChunk with precompiled file path in webpack 5 or alternative


Earlier in webpack version 4 and node 14 version, runtimeChunkName was with pre-comipled chunk filepath, but now this is not working in webpack 5.

const beforeRenderPath = before-render/js/dist/BeforeRenderActivity-dyn;

const runtimeChunkName = env === 'development' ? ../${beforeRenderPath} : ./plugins/${beforeRenderPath};

optimization: {
  splitChunks: {
    cacheGroups: {
      antd: {
        name: 'antd',
        test: (module) => {
          return (
            /antd|rc-/.test(module.context) ||
            /ant-design[\\/]icons/.test(module.context)
          );
        },
        chunks: 'all',
        priority: 2,
        enforce: true
      },
      ... some_more_vendors,
  runtimeChunk: {
    name: runtimeChunkName
  }

How to serve runtimeChunk name with the help of filepath reference in webpack 5?

Error received is: Refused to execute script from because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled

Entry points looks like this:

This is served from plugin.json which is hash map.

{
  "../../conf/login/js/dist/LoginView": "./plugins_on_premise/login/js/LoginView.tsx",
  "../auth-provider/js/dist/AuthProvider": "./plugins_on_premise/auth-provider/js/AuthProvider.ts",
  "../auth-provider/js/dist/RenewTokenActivity-dyn": "./plugins_on_premise/auth-provider/js/RenewTokenActivity-dyn.tsx",
  "../_context-switch/js/dist/ContextSwitchActivity-dyn": "./plugins_on_premise/_context-switch/js/ContextSwitchActivity-dyn.tsx",
  "../change-password/js/dist/ChangePasswordActivity-dyn": "./plugins_on_premise/change-password/js/ChangePasswordActivity-dyn.tsx",
  "../before-render/js/dist/BeforeRenderActivity-dyn": 
  "./plugins/before-render/js/BeforeRenderActivity-dyn.tsx"
}

These are the versions in use:

"webpack": "5.88.2",
"webpack-bundle-analyzer": "4.9.0",
"webpack-chunk-rename-plugin": "1.0.3",
"webpack-cli": "5.1.4",
"webpack-dev-middleware": "6.1.1",
"webpack-dev-server": "4.15.1",
"webpack-hot-middleware": "2.25.4"

runtimeChunkName in webpack-4 was pointing to a specific file: BeforeRenderActivity as a dependency or pre-check earlier. But wepack 5 says, now need to use dependOn with import syntax.

So what should be correct syntax for entries and now going forward runTimeChunkname should be kept or deleted or modified for optimization benefits that was carried from webpack 4.

Requesting a working example or steps to fix this.

How to fix this issue with multiple plugin entry that requires one precompiled entry in webpack 5?


Solution

  • I'm not quite sure of what you mean when you say -

    runtimeChunkName was with pre-comipled chunk filepath

    The documentation for v5 and v4 for runtimeChunk is same and the only effect this takes is appending the provided path to the runtime module generated for optimization, as mentioned in the docs. So by providing a value like ../${beforeRenderPath} what you were trying to do is load the module, one directory up for each runtime module?

    From the statement -

    runtimeChunkName in webpack-4 was pointing to a specific file: BeforeRenderActivity as a dependency or pre-check earlier. But wepack 5 says, now need to use dependOn with import syntax.

    I think my speculation above is correct and as mentioned by you in response to my comment on the post, what you're expecting is to load a specific set of modules for every runtime module, instead of just having one of those shared module included globally and be used everywhere.

    The shared entry point should be loaded for all entry points in runtime and thats the ask.

    To do that in Webpack 5, here's what you'll need to do -

    const env = process.env.NODE_ENV; // or whatever
    let beforeRenderPaths = ["before-render/js/dist/BeforeRenderActivity-dyn", "auth-provider/js/dist/RenewTokenActivity-dyn"];
    
    beforeRenderPaths = beforeRenderPaths.map(path => env === "development" ? `../${path}` : `./plugins/${beforeRenderPath}`);
    
    module.exports = {
      //...
      entry: {
        a: { import: "./src/a.js", dependOn: "shared" },
        b: { import: "./src/b.js", dependOn: "shared" },
        c: { import: [ "./src/c.js", "./src/f.js"], dependOn: "shared"},
        'shared': beforeRenderPaths,
      },
      //...
      runtimeChunk: true
    };
    

    And then, make sure to import the shared modules in all the places like so -

    import 'before-render/js/dist/BeforeRenderActivity-dyn';
    import 'auth-provider/js/dist/RenewTokenActivity-dyn';
    

    Let me know if I misunderstood something or missed something.

    NOTE: This practice is frowned upon by webpack. Read this for more information and check this for understanding exactly why. I'm guessing that your use case is to do some sort of housekeeping stuff before loading anything, like authentication, checking active plan etc.