#css#typescript#tooling

How We Test UI Without Snapshot Tests

· 3 min read

Every codebase has one area everyone is a little afraid to touch. On our team, it was everything related to server-side rendering.

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 server-side rendering rather than building anything.

Where we started

The first symptom was subtle. Nothing failed outright, but server-side rendering kept drifting in the wrong direction, and every fix seemed to make the next one harder.

We had good intentions. We even had a document describing how server-side rendering should work. The trouble was that the document and the code had quietly gone their separate ways.

The fix

Rather than a big-bang rewrite, we migrated one module at a time over about 4 weeks, keeping both paths alive behind a flag.

The core of it looks like this:

.card-list {
  container-type: inline-size;
}

@container (min-width: 36rem) {
  .card {
    display: grid;
    grid-template-columns: 12rem 1fr;
    gap: 1.5rem;
  }
}

This alone let us delete a surprising amount of code elsewhere in the project.

A few things that helped along the way:

  • Measure before and after, even if it's just a rough number in a spreadsheet.
  • Make the default the safe choice, not just the documented one.
  • Write the migration guide before writing the migration.
  • Pair on the first few changes so the knowledge doesn't live in one head.

Trade-offs

The biggest cost was social, not technical. Changing how people think about server-side rendering takes much longer than changing the code.

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

Closing thoughts

Six months in, nobody on the team wants to go back. That's about the best review a change like this can get.

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