When we talk about multithreading in Node.js, we often mention Worker Threads (which we covered in this post). But did you know that Web Workers, a feature originally designed for browsers, can also be used in Node.js?
Today, weβll dive into how Web Workers work in Node.js, when to use them, and how they compare to Worker Threads. π
π₯ What Are Web Workers?
Web Workers are separate JavaScript threads that run independently from the main execution thread. They are commonly used in browsers to prevent blocking the UI when running CPU-intensive tasks.
But as of Node.js 12, Web Workers are also supported in Node.js, allowing you to run JavaScript code in parallel just like Worker Threads!
βοΈ How Do Web Workers Work in Node.js?
In a browser, Web Workers are created using the Worker
constructor with a separate JavaScript file. Node.js follows a similar pattern but with some key differences:
β
Runs scripts in separate threads.
β
Uses Message Passing (postMessage) for communication.
β
Can be used alongside Worker Threads.
However:
β Web Workers in Node.js do not share memory (unlike Worker Threads).
β You canβt use Node.js built-in modules inside Web Workers.
π Creating a Simple Web Worker in Node.js
Let's build a basic Web Worker that performs CPU-intensive calculations in the background.
Step 1: Create a Web Worker (worker.mjs
)
// Web Worker script (worker.mjs)
onmessage = (event) => {
const num = event.data;
const result = fibonacci(num);
postMessage(result);
};
function fibonacci(n) {
return n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
Step 2: Use the Web Worker in main.mjs
import { Worker } from "worker_threads"; // Using Worker from Worker Threads API
const worker = new Worker(new URL("./worker.mjs", import.meta.url));
worker.postMessage(40); // Send a task to the worker
worker.on("message", (result) => {
console.log("β
Worker result:", result);
});
worker.on("error", (err) => {
console.error("β Worker error:", err);
});
worker.on("exit", (code) => {
console.log(`Worker exited with code ${code}`);
});
π Whatβs Happening?
worker.mjs
calculates Fibonacci numbers when it receives a message.- The main thread sends
40
to the worker usingpostMessage()
. - The worker returns the result via
postMessage()
.
This keeps the main thread responsive while offloading heavy computation to a background thread.
β‘ Web Workers vs. Worker Threads
Both Web Workers and Worker Threads allow parallel execution in Node.js, but they have key differences:
Web Workers vs. Worker Threads Comparison
Web Workers π
- Designed for: Browsers
- Node.js Support: β Yes (Node.js 12+)
- Memory Sharing: β No
- Can use Node.js Modules: β No
- Communication: Message passing (postMessage)
Worker Threads π
- Designed for: Node.js
- Node.js Support: β Yes (Node.js 10+)
- Memory Sharing: β
Yes (
SharedArrayBuffer
) - Can use Node.js Modules: β Yes
- Communication: Message passing + Shared Memory
When to Use What?
- Use Web Workers β If you're porting browser-based code to Node.js.
- Use Worker Threads β If you need shared memory & access to Node.js modules.
- Use Both Together β For a mix of frontend + backend parallelization.
π― Real-World Use Case: Offloading JSON Processing
Imagine your Node.js API receives large JSON payloads that need processing. Instead of blocking the event loop, letβs offload JSON parsing to a Web Worker.
Step 1: Create the Web Worker (json-worker.mjs
)
onmessage = (event) => {
const jsonData = event.data;
const processedData = JSON.stringify(jsonData, null, 2); // Pretty-print JSON
postMessage(processedData);
};
Step 2: Use the Web Worker in server.mjs
import express from "express";
import { Worker } from "worker_threads";
const app = express();
app.use(express.json());
app.post("/process-json", (req, res) => {
const worker = new Worker(new URL("./json-worker.mjs", import.meta.url));
worker.postMessage(req.body);
worker.on("message", (processedJson) => res.send(processedJson));
worker.on("error", (err) => res.status(500).send(err.message));
});
app.listen(3000, () => console.log("π Server running on port 3000"));
How This Helps
β
Main thread stays free β No blocking, even with large JSON.
β
Multiple requests handled efficiently β Each request gets its own worker.
β
Ideal for heavy computations β Parsing, data processing, etc.
π₯ Final Thoughts
Web Workers in Node.js provide a parallel execution model similar to Worker Threads, but with some key trade-offs.
- β Great for running browser-style parallel tasks.
- β Limited because they donβt support Node.js modules or shared memory.
- β Can be combined with Worker Threads for full multithreading power.
Want to push Node.js performance even further? Check out this post on Worker Threads for an even deeper dive! π