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 v25.2.1 and below. Please 👍 this issue to show your support!
Using npm:
$ npm i @apacheli/web-workersUsing Deno:
$ deno add npm:@apacheli/web-workersUsing Bun:
$ bun install @apacheli/web-workersWhile 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");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: trueimport "@apacheli/web-workers/global.js";
// ^ Does nothing in Deno and Bun
console.log(Worker === globalThis.Worker);
// => Node: true
// => Deno: true
// => Bun: trueconsole.log(Worker === globalThis.Worker);
// => Node: Uncaught ReferenceError: Worker is not defined
// => Deno: true
// => Bun: trueIn the event you need this package for the browser for some reason, imports from
esm.sh are available.
<script
src="https://esm.sh/@apacheli/web-workers/global.js"
type="module"
></script>If you encounter any bugs, feel free to open an issue.