#javascript#typescript#css

Shipping Less JavaScript Without Rewriting Everything

· 3 min read

A colleague asked me last week why our team cares so much about hydration. I gave a rambling answer, so here is the longer, more organized version.

The setup was ordinary: Astro at the edges, Vue 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 hydration 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 36% of the time spent on a typical change went into working around hydration rather than building anything.

Trying something different

The key insight was to treat hydration as part of the interface rather than an implementation detail. Once we did that, most of the other decisions followed naturally.

Stripped of the project-specific bits, 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);
  };
}

It's tempting to generalize this into a library. Resist that urge until you've needed it in at least three places.

A few things that helped along the way:

  • Pair on the first few changes so the knowledge doesn't live in one head.
  • Measure before and after, even if it's just a rough number in a spreadsheet.
  • Agree on what "done" means before the first pull request.

Trade-offs

We still haven't solved form validation. That's a post for another day, and honestly, I'm not sure we'll get it right the first time either.

None of this is free. The new approach is a bit more verbose, and newcomers occasionally ask why we don't just use Svelte for everything. That's a fair question with a boring answer: we tried, and it made hydration harder to reason about.

Closing thoughts

That's it for now. Next time I'll dig into server-side rendering, which turned out to be closely related.

RK
Rafael Kim
Frontend engineer in Brisbane. Writing about frontend engineering.