Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 974
user2521651 Avatar asked Aug 02 '26 07:08

user2521651


2 Answers

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)

like image 87
Hunter Larco Avatar answered Aug 04 '26 23:08

Hunter Larco


I think one of the webpack plugins is causing this issue. to detect this you can use circular-dependency-plugin

Circular dependencies are often a necessity in complex software, the presence of a circular dependency doesn't always imply a bug, but in the case where you believe a bug exists, this module may help find it.

// webpack.config.js
const CircularDependencyPlugin = require('circular-dependency-plugin')
 
module.exports = {
  entry: "./src/index",
  plugins: [
    new CircularDependencyPlugin({
      // `onStart` is called before the cycle detection starts
      onStart({ compilation }) {
        console.log('start detecting webpack modules cycles');
      },
      // `onDetected` is called for each module that is cyclical
      onDetected({ module: webpackModuleRecord, paths, compilation }) {
        // `paths` will be an Array of the relative module paths that make up the cycle
        // `module` will be the module record generated by webpack that caused the cycle
        compilation.errors.push(new Error(paths.join(' -> ')))
      },
      // `onEnd` is called before the cycle detection ends
      onEnd({ compilation }) {
        console.log('end detecting webpack modules cycles');
      },
    })
  ]
}
like image 24
Yilmaz Avatar answered Aug 04 '26 23:08

Yilmaz