Reference · print-friendly
One page for design reviews. Walk gates top to bottom; stop when a row rejects the current candidate.
| If… | Prefer… |
|---|---|
| Work already fits interaction/frame budgets on target devices | Stay on main; measure first |
| Bottleneck is layout/paint/React commit, not pure JS | Main-thread render work — workers can’t fix DOM cost |
| Long pure compute/parse freezes input | Dedicated worker (or yield/chunk if simpler) |
| Offline / cache / push / request intercept | Service worker — different tool |
| If… | Prefer… |
|---|---|
| One page; offload CPU / pure data work | Dedicated Worker |
| Tabs only need to notify each other | BroadcastChannel |
| One shared process (one socket, shared engine, multi-window hub) | SharedWorker (same origin; verify support) |
| Network proxy / offline shell | Service Worker |
| If… | Plan… |
|---|---|
| Need DOM / window / framework render in the “worker” | Split pure core → worker; keep render on main — or reject |
| Small control messages / modest state | Structured clone postMessage |
| Large binary you won’t need again on sender | Transfer (ArrayBuffer in transfer list) |
| Huge or high-frequency logical state | Patches / chunking — not full-state clone every tick |
| Multi-job worker |
Typed messages + correlation id +
onerror
|
new Worker(new URL("./w.js", import.meta.url)) /
Vite ?worker
terminate() on unmount;
SharedWorker port hygiene
“We use main | dedicated | shared | BroadcastChannel | SW because problem class; messages are clone | transfer | patches; we own lifecycle + bundler + one risk.”