Building Forms That Don't Fight the Browser
I've been working with Svelte for about 3 years now, and my opinions on Core Web Vitals have changed more than I expected.
The setup was ordinary: Svelte at the edges, Playwright doing most of the heavy lifting, and a handful of scripts nobody wanted to own. It worked well until usage roughly doubled over a single quarter.
How we got here
We had good intentions. We even had a document describing how Core Web Vitals should work. The trouble was that the document and the code had quietly gone their separate ways.
When we finally measured, the numbers were worse than anyone guessed. Around 38% of the time spent on a typical change went into working around Core Web Vitals rather than building anything.
How it works
The fix turned out to be smaller than expected. Instead of adding another layer, we removed one and leaned on what Svelte already gives you out of the box.
The core of it looks like this:
export function debounce<T extends (...args: any[]) => void>(fn: T, wait = 200) {
let timer: ReturnType<typeof setTimeout> | undefined;
return (...args: Parameters<T>) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), wait);
};
}
This alone let us delete a surprising amount of code elsewhere in the project.
A few things that helped along the way:
- Make the default the safe choice, not just the documented one.
- Write the migration guide before writing the migration.
- Measure before and after, even if it's just a rough number in a spreadsheet.
- Delete dead code aggressively; it's the cheapest refactor there is.
Where this breaks down
There are cases where this falls apart. If your team is very small or your traffic is very spiky, the extra moving parts may not pay for themselves.
The biggest cost was social, not technical. Changing how people think about Core Web Vitals takes much longer than changing the code.
Wrapping up
If you take one thing away from this, let it be this: Core Web Vitals is a design decision, not a cleanup task. Make it early and make it on purpose.