Search code examples
javascriptwebpackweb-worker

Webpack warning using webworker: Circular dependency between chunks with runtime


I'm using Webpack 5 for a project, and just tried to move some logic out into a WebWorker. Here's how I'm creating the worker:

persistenceWorker = new Worker(
  new URL('app/engine/persistence/worker', import.meta.url),
);

However, I now have this warning from webpack:

Circular dependency between chunks with runtime (main, src_app_engine_index_ts)
This prevents using hashes of each other and should be avoided.

It seems like this is because my worker file imports code that transitively imports the file that is creating the worker. I don't think this is avoidable in the architecture of my program. I don't see how this is a problem, though - nothing imports the worker module, so the references should all go one direction. It seems like it's counting creating the worker as a dependency, even though the file creating the worker is not actually importing the code in the worker file.

Is there a way to fix this? Refactoring my project to remove the "circular dependency" is probably a no go.

And how much of a problem is this warning? Everything works fine if I close the warning out, and I'm not clear what "This prevents using hashes of each other" means in practical terms.


Solution

  • Typically webpack will bundle files named using the format [name].[contenthash].js for example, the bundle "index" might be index.e64fc3.js. This is done so that new deployments of your frontend wont use client-side js cached from previous versions of your application. See this documentation for more details on content hashing: https://webpack.js.org/guides/caching/

    This error is informing you that your two circular dependencies cannot be named with their content hash included in the bundle file name. This is because the content hash of each file now depends on the content hash of the other (a circular dependency webpack cannot resolve).

    The impact of this is questionable. On one hand, your application will work. Especially locally. However, when deploying you now run the risk of not invalidating client-side caches for your worker and worker creation bundles. And since they may not be cached with the same expiry time, you may even run into production scenarios where you have a version mismatch between your worker and caller code (yikes).

    You can avoid this by using a non-content-dependent salt in your bundle output. Maybe a version string or release date? It's not quite as nice seeing as every release will invalidate the two bundles even if they contain no changes, but it will alleviate the warning and potential side effects.

    Looking at webpack's built-in filename template strings it doesn't look like anything satisfies the above solution. You can trivially roll this out yourself using something like:

    // webpack.config.js
    
    module.exports = {
      // ...
      output: {
        filename: (pathData) =>
            `${pathData.chunk.name}.${process.env.npm_package_version}.js`;
      },
    };
    

    Note that process.env.npm_package_version is populated by npm run (see https://docs.npmjs.com/cli/v9/using-npm/scripts#packagejson-vars)