A long calculation on the main thread can block clicks, typing, and painting. A Web Worker runs JavaScript in a separate global context and communicates with the page by messages.
const worker = new Worker(
new URL("./search.worker.js", import.meta.url),
{ type: "module" },
);
worker.addEventListener("message", ({ data }) => {
renderResults(data);
});
worker.postMessage({ query, records });// search.worker.js
self.addEventListener("message", ({ data }) => {
const results = expensiveSearch(data.records, data.query);
self.postMessage(results);
});Keep the message boundary deliberate
- Send the smallest data the worker needs; structured cloning can itself be costly for large object graphs.
- Use transferable buffers for binary data when ownership can move to the worker.
- Handle worker errors and terminate it when the owning interface is permanently removed.
Workers cannot manipulate the page DOM directly. Send results back to the main thread and update the interface there.
