Web Workers

As of webpack 5, you can use Web Workers without worker-loader.

Syntax

new Worker(new URL('./worker.js', import.meta.url));
// or customize the chunk name with magic comments
// see https://webpack.js.org/api/module-methods/#magic-comments
new Worker(
  /* webpackChunkName: "foo-worker" */ new URL('./worker.js', import.meta.url)
);

The syntax was chosen to allow running code without bundler, it is also available in native ECMAScript modules in the browser.

Note that while the Worker API suggests that Worker constructor would accept a string representing the URL of the script, in webpack 5 you can only use URL instead.

Example

src/index.js

const worker = new Worker(new URL('./deep-thought.js', import.meta.url));
worker.postMessage({
  question:
    'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
});
worker.onmessage = ({ data: { answer } }) => {
  console.log(answer);
};

src/deep-thought.js

self.onmessage = ({ data: { question } }) => {
  self.postMessage({
    answer: 42,
  });
};

Node.js

Similar syntax is supported in Node.js (>= 12.17.0):

import { Worker } from 'worker_threads';

new Worker(new URL('./worker.js', import.meta.url));

Note that this is only available in ESM. Worker in CommonJS syntax is not supported by either webpack or Node.js.

Cross-Domain and Dynamic Web Workers

In some setups, you may need your worker script to be hosted on a different origin
(for example, on a CDN or within a micro-frontend).
Webpack supports this, but the worker must know the correct public path at runtime.

Setting a dynamic public path safely

The recommended approach is to define __webpack_public_path__ at the beginning of your worker entry file, before any imports.
This lets webpack resolve chunk URLs correctly without editing generated code:

// worker.js

// Define the public path dynamically before loading other modules
/* eslint-disable camelcase */
__webpack_public_path__ = self.location.origin + '/assets/';

// Then import or execute the rest of your worker logic
importScripts('deep-thought.js');

1 Contributor

chenxsan