tooling.report

feature

Between new worker type

Can entry bundles be created for other contexts?

Person in shorts with blue hair walking left

Introduction

There are a number of different scenarios where it's necessary to bundle some code separately for a different JavaScript context. Web Workers are perhaps the most popular case, however the same underlying functionality is necessary in order to bundle code for use in Service Workers, Module Workers and Worklets. Since many tools apply special handling to Web Workers, it can take time to catch up with new worker variants.

The Test

This test checks that it's possible to reuse the underlying functionality of code splitting between workers for new or custom context types, without having to wait for a new release of the build tool. Effectively, it tests that it's possible to create an entry point and obtain its bundled URL at runtime.

index.js

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

new InterestingNewWorkerType(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 of bundling these modules should be two or three files: one bundle for the main thread and one for the worker thread, and ideally a shared bundle for the logCaps utility method that can be used by both bundles.

Conclusion

browserify

As Browserify does not support loading code dynamically, it cannot provide a JS file as a URL.

Issues

  • N/A
parcel

There is a plugin infrastructure for Parcel 2 that is probably capable of solving this, but at the time of writing, the documentation doesn’t really tell me how.

Issues

rollup

rollup-plugin-off-main-thread allows you to import a JS file as a worker and returns the URL. 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

Bundling Web Workers is possible in Webpack using one of the many add-ons like worker-loader or worker-plugin, however there is no documented solution for accessing the underlying behavior: compiling a new entry starting from a given module and returning its bundle URL. There have been some attempts to support this in worker-loader, but at present the only available solution is worker-plugin/loader:

import workerUrl from 'worker-plugin/loader!./my-worker';
new Worker(workerUrl);

This makes it possible to bundle code for use in new worker-like environments like Worklets, however code splitting between the "host" and "child" sets of bundles is still not supported.