Skip to content

apacheli/web-workers-polyfill

Repository files navigation

Web Workers Polyfill for Node.js

A polyfill for Web Workers for Node.js.

  • Adds ErrorEvent
  • Adds Worker
  • Adds globalThis.self

Note

Web Workers are currently not supported natively in Node.js v22.4.0. Please 👍 this issue to show your support!

Installing

$ npm i @apacheli/web-workers

Useful Links

Examples

Using CommonJS

While I recommend using ESM instead of CommonJS, the focus of this module is to add Web Workers support to Node.js.

Here is a simple example:

main.js

const { Worker } = require("@apacheli/web-workers");

const worker = new Worker("./worker.js");

worker.addEventListener("message", (event) => {
  console.log("message from worker.js:", event.data);
  worker.terminate();
});

worker.postMessage("Hello, World!");

worker.js

const { self } = require("@apacheli/web-workers");

self.addEventListener("message", (event) => {
  console.log("message from main:", event.data);
});

self.postMessage("hi");

Yields the following:

$ node main.js
message from worker.js: hi
message from main: Hello, World!

Regularly importing the module does not modify the global namespace. Instead, you can import @apacheli/web-workers/global script to modify the global namespace:

main.js

require("@apacheli/web-workers/global");

const worker = new Worker("./worker.js");

worker.addEventListener("message", (event) => {
  console.log("message from worker.js:", event.data);
  worker.terminate();
});

worker.postMessage("Hello, World!");

worker.js

require("@apacheli/web-workers/global");

self.addEventListener("message", (event) => {
  console.log("message from main:", event.data);
});

self.postMessage("hi");

Using ESM

Note

You may have to append .js to the import.

main.js

import "@apacheli/web-workers/global.js";

const worker = new Worker(new URL("./worker.js", import.meta.url), {
  type: "module",
});

worker.addEventListener("message", (event) => {
  console.log("message from worker:", event.data);
  worker.terminate();
});

worker.postMessage("Hello, World!");

worker.js

import "@apacheli/web-workers/global.js";

self.addEventListener("message", (event) => {
  console.log("message from main:", event.data);
});

self.postMessage("hi");

For maximum cross-platform compatibility, you should use URL to specify your worker. new Worker("./worker.js") will still work in Node.js though.

If you use platforms such as Deno and Bun, the global namespace will not be tampered. It will just reexport the already existing implementations.

import { Worker } from "@apacheli/web-workers";
// ^ Reexports `Worker` if it already exists

console.log(Worker === globalThis.Worker);
// => Node: false - because globalThis.Worker does not exist
// => Deno: true
// => Bun: true
import "@apacheli/web-workers/global.js";
// ^ Does nothing in Deno and Bun

console.log(Worker === globalThis.Worker);
// => Node: true
// => Deno: true
// => Bun: true
console.log(Worker === globalThis.Worker);
// => Node: Uncaught ReferenceError: Worker is not defined
// => Deno: true
// => Bun: true

License

MIT License