Web Workers allow offloading expensive computations on a background thread in browsers.
vite supports creating Web Workers with new Worker.
const url = new URL("./feed.ts", import.meta.url); // 👈 Add `import.meta.url` for Vite
const newWorker = new Worker(url, { type: "module" });Since Web Workers are processes outside of React, this is a valid case of using useEffect to create and interact with a worker.
Make sure to call
terminate()inuseEffectclean up function.
Interacting with a worker consists of two operations:
- Sending messages (
postMessage) - Receiving messages (
onmessage)
onmessage can be made type-safe by passing the expected messages inside MessageEvent (e.g. MessageEvent<WorkerResponse>).
postMessage accepts any as parameter. We can make it type-safe as well by using satisfies to enforce the value provided:
worker.current.postMessage({
type: "feed.get",
source: "https://www.sandromaglione.com/feed",
} satisfies WorkerMessage);The worker script implements onmessage as well. Inside it you can perform any (expensive) computation, and then send back a message with the result to the main thread (postMessage).
Inside vite.config.ts you can specify the output format of the worker bundle (e.g. "es"):
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react()],
worker: { format: "es" },
});Make sure to also specify type: "module" when creating the Worker instance (otherwise you will get the following error: SyntaxError: Cannot use import statement outside a module):
const url = new URL("./feed.ts", import.meta.url);
const newWorker = new Worker(url,
{ type: "module" }
);