Web workers allow you to push work outside of main execution thread of JavaScript, making them convenient for lengthy computations and background work.
Moving data between the main thread and the worker comes with communication-related overhead. The split provides isolation that forces workers to focus on logic only as they cannot manipulate the user interface directly.
As discussed in the Build Targets chapter, webpack allows you to build your application as a worker itself. To get the idea of web workers better, we'll write a small worker to bundle using webpack.
A worker has to do two things: listen to messages and respond. Between those two actions, it can perform a computation. In this case, you accept text data, append it to itself, and send the result:
src/worker.js
self.onmessage = ({ data: { text } }) => {
self.postMessage({ text: text + text });
};
The host has to instantiate the worker and then communicate with it:
src/component.js
export default (text = HELLO) => {
const element = document.createElement("h1");
const worker = new Worker(
new URL("./worker.js", import.meta.url)
);
const state = { text };
worker.addEventListener("message", ({ data: { text } }) => {
state.text = text;
element.innerHTML = text;
});
element.innerHTML = state.text;
element.onclick = () => worker.postMessage({ text: state.text });
return element;
};
After you have these two set up, it should work as webpack detects the Worker
syntax. As you click the text, it should mutate the application state when the worker completes its execution. To demonstrate the asynchronous nature of workers, you could try adding delay to the answer and see what happens.
Due to the cost of serialization, passing data between the host and the worker can be expensive. The cost can be minimized by using Transferable objects and in the future, sharing data will become possible thanks to SharedArrayBuffer.
Before webpack 5, worker-loader was the preferred option and it can still be used if you want more control over the bundling process.
workerize-loader and worker-plugin let you use the worker as a regular JavaScript module as well given you avoid the self
requirement visible in the example solution.
threads.js provides a comprehensive solution for more complex setups and it includes features such as observables and thread pools out of the box. There's a custom threads-plugin you can use to integrate it with webpack.
The critical thing to note is that the worker cannot access the DOM. You can perform computation and queries in a worker, but it cannot manipulate the user interface directly.
To recap:
You'll learn about internationalization in the next chapter.
This book is available through Leanpub (digital), Amazon (paperback), and Kindle (digital). By purchasing the book you support the development of further content. A part of profit (~30%) goes to Tobias Koppers, the author of webpack.