Skip to main content

Search rules

Search all UI Guides rules by name, category, or source

performanceVercel

Keep Long Tasks Off the Main Thread

MUST

MUST: Move expensive computation off the main thread — anything past ~50ms is a long task by Core Web Vitals and eats INP; an 800ms sync loop paints no frames and queues every click, while the CSS spinner keeps turning on the compositor and disguises the freeze as progress. Post it to a Web Worker, or chunk it and yield with `scheduler.yield()` if it must touch the DOM.

Move long-running computation into a Web Worker so the page stays interactive

const worker = new Worker(new URL("./crunch.worker.ts", import.meta.url), { type: "module" });
worker.postMessage(rows);
worker.onmessage = (e) => setResult(e.data);

Bad

Good

Why it matters

The main thread renders every frame, runs every event handler, and executes your JavaScript — one queue, one worker. A synchronous computation that runs for 800ms does not make the page slow, it makes it dead: no frames paint, clicks and keystrokes sit in the queue, and a CSS spinner is the only thing still moving (because it is on the compositor) which makes the freeze look like a working loading state.

Anything past roughly 50ms is already a "long task" by Core Web Vitals' definition and eats directly into INP. Post the work to a Web Worker — it runs on its own thread and messages the result back — or, if it genuinely must touch the DOM, chunk it and yield with scheduler.yield() between slices.

Built by Gleb Stroganov, design engineer at Evil Martians.

The rules come from other people's skills and guidelines — Vercel, Rauno Freiberg, @Ibelick, impeccable, Emil Kowalski, Tailwind, RAMS — each one credited on the Sources page. The work here is extraction and wiring: every rule is pulled into one corpus, given a good and a bad example you can operate, a MUST/SHOULD/NEVER rule an agent can paste, and a link back to where it came from.