tooling.report

feature

Between workers

Can bundles be shared between the main thread and workers?

Person in shorts with blue hair walking left

Introduction

Web Workers are great for moving long blocking work and large modules off the main thread, keeping UI updates fast and smooth. In many cases, code running in a worker will need to rely on some of the same modules as code used on the main thread or in other workers.

The Test

This test checks to see if it's possible to share modules between Web Workers and the main thread, or between multiple workers. Since few browsers support ECMAScript modules in workers, a custom module format or runtime module loader is necessary in order to pass this test.

index.js

import workerURL from 'get-worker-url-somehow';
import { logCaps } from './utils.js';

new Worker(workerURL);
logCaps('This is index');

worker.js

import { logCaps } from './utils.js';
logCaps('This is worker');

utils.js

export function logCaps(msg) {
  console.log(msg.toUpperCase());
}

The result should be three scripts: one for the main thread containing index.js, one for the worker containing worker.js, and one for the dependencies shared by both (logCaps()). As with other bundle URL tests, the worker's URL must be hashed.

Conclusion

browserify

Browserify's module format works in both the main thread and workers.

However, Browserify's code-splitter, factor-bundle, is limited to creating a single common chunk, and the common chunk needs to be loaded manually, so this will have scaling problems in larger code bases.

Issues

  • N/A
parcel

Parcel handles this by default.

Issues

rollup

rollup-plugin-off-main-thread picks up usage of new Worker('./script.js') and creates a chunk for ./script.js. Rollup makes this simple via its emitFile method which lets you create a new chunk dynamically and get its eventual URL. Since workers are just another entry point, this primitive is a perfect and extensible fit.

webpack

Using new Worker(new URL("./worker", import.meta.url)) will create a worker that is able to share dependencies with the main bundle (and other worker bundles).