The round trips a web app makes

INPUT · Slides

Where the HTML gets built

01 / 11

The same screen, three ways of building the HTML

Last lesson we split the container round trip (the same whoever looks) from the data round trip (different from person to person). This time we go one level further into that first one.

Even for pages that look exactly the same, there are three answers to when and where the finished string of HTML gets built.

  • Built in the browser (CSR) … the HTML that arrives is nearly empty. It gets put together once the JavaScript runs
  • Built on the server (SSR) … on every request, the server builds finished HTML and returns it
  • Built in advance (SSG) … built before release and handed out as a file

None of them is the right answer. The goal of this chapter is to be able to say what each one buys and what it gives up. The three things being fought over are a fast first paint, fresh data, and a light server.

02 / 11

CSR — built in the browser

CSR (client-side rendering) is the way that puts the screen together in the browser.

The HTML that comes from the server is almost empty. It sets aside one place to put things, and beyond that it only says to load the JavaScript. From there the running order is this.

  • Download the JavaScript file
  • Run it
  • Send a data round trip and get the contents
  • Put the screen together from the data that came back

So there are four stages to wait through before the contents show, which makes the first paint easy to be slow. During that time the screen is blank, or showing nothing but a loading mark.

In exchange, the server only has to hand out the files sitting there, so it stays light. There is one other snag: search engines and social previews sometimes cannot read the contents, because the HTML that reached them was empty.

<div id="app"></div><script src="app.js">

03 / 11

SSR — the server builds it on every request

SSR (server-side rendering) is the way where the server builds finished HTML on every request and returns it.

The server looks in the database, fits in the contents for that person, and returns the HTML it has made. The browser can just draw what arrived, so there is only one stage to wait through.

There are two things you gain: the first paint is fast, and it is always fresh. The data is read just before the response goes out, so an update from a second ago is already in there. And because the HTML that arrives has contents in it, search engines and previews can read it too.

What you pay in return is load on the server. A hundred thousand requests means a hundred thousand builds. That takes a completely different amount of power from returning a file that is sitting there.

① request② look in the DB③ build the HTML④ finished HTML

04 / 11

SSG — built in advance

SSG (static site generation) is the way where the HTML is built before release and kept.

The building happens once. After that you are only handing out the finished HTML as a file that is sitting there. Nothing has to be worked out after a request arrives.

Which makes it the fastest and the cheapest. No program runs, so it drops straight onto anything built for handing out files. The HTML that arrives has contents in it, so search engines and previews are no trouble either.

It has one weak point, but it is a big one: changing the contents means building again. It is frozen with the contents it had at build time, so if the data changes afterwards, the HTML being handed out stays old.

So what SSG suits is things that are the same whoever looks and hardly ever change.

before release: build HTMLafter release: hand out files

05 / 11

The three side by side

Look at them along the same four lines and the differences in character come out clearly.

How fast the first paint is
- SSG … fastest (it just returns what is sitting there)
- SSR … fast (the building takes time)
- CSR … easily slow (you wait for the JS to run and the data to arrive)

How fresh the data is
- SSR … always fresh (read just before the response)
- CSR … fresh (fetched after the page opens)
- SSG … frozen at build time

Load on the server
- SSG … lightest
- CSR … light (only handing out files)
- SSR … heavy (works on every request)

Whether you have to build again
- SSG … changing the contents means building again
- SSR and CSR … no (they read at the time)

As you can see, no way of doing it comes first in everything. So the question is not "which is correct" but "what does this page put first".

06 / 11

ISR — build it in advance, then build it again later

The only weak point of SSG was going stale. So — build it again every so often. That idea is what gets called ISR (incremental static regeneration), or just regeneration.

There are two ways to give the cue.

  • Go by time … "if it is more than ten minutes since it was built, build it again"
  • Say so on update … when an article is rewritten, tell it "build that page again"

The important part is that the old one keeps being handed out while the new one is being built. So nobody is left waiting. The speed stays what SSG had, and only the staleness goes down.

It is not completely up to date. Think of it as the middle way: you accept "it might be up to ten minutes old" and in exchange you do not pay the load that SSR would cost.

prebuilt → after 10 minif stale, build again

07 / 11

How to choose

The handle is the same one you used last lesson: is it the same whoever looks, or does it change from person to person.

  • The same whoever looks, and hardly ever changes … build in advance (SSG). The company profile, the terms of use, an article you have finished writing
  • The same whoever looks, but changes now and then … build in advance plus regeneration (ISR). A news listing, a product listing
  • Changes from person to person, or changes constantly … build on every request (SSR), or fetch in the browser (CSR). Your own order history, notifications, an admin screen

And the most important thing. This is not something you decide once for a whole site — it can differ from page to page.

Inside one site: the front page built in advance, the product listing regenerated, your own page built on every request. That is fine. Ask each page in turn whether it is the same whoever looks, and it settles itself.

08 / 11

Going SSR does not make the data round trips go away

Here is an easy mix-up. Some people come away thinking "with SSR you do not need an API", and that is wrong.

It is true that for the first page, the server reads the data and puts it in the HTML. So for showing that one page, no data round trip from the browser is needed.

But what about everything the person does after that?

  • Pressing "show more" to bring out the next twenty
  • Changing the sort from newest to most popular
  • Pressing the post button to write something

Every one of those is data that became necessary at that moment. What was in the HTML was only what existed when that first page was built. So from here you end up sending data round trips after all.

SSR replaces the first page only. The round trips after that stay, whichever way you build.

09 / 11

Keep track of which side the code runs on

Once the server is building HTML too, the same code, written in the same language, runs in two places. There are two things to watch out for here.

① The server does not have the features the browser provides. window, document, the call that measures the width of the screen — the browser is what provides those. Touch one while the server is building and it fails on the spot. That is what is really behind "but it was fine when I ran it in the browser".

② Do not write secrets into the side that runs in the browser. As we did in the first lesson, everything you send to the browser is visible. Keys for outside services, and the details for connecting to a database, go somewhere that only runs on the server.

Both are avoided by keeping track, first of all, of which side this code runs on.

on the server: no windowin the browser: no keys

10 / 11

Hydration — visible but not pressable

The moment the HTML the server built arrives, the screen is visible. But it is not pressable yet.

The HTML that arrived is a string, and none of "when this button is pressed, do this" is in it. Giving it that behaviour is the job of the JavaScript that arrives afterwards.

The JavaScript in the browser hooking itself onto the HTML the server built, until it can be operated, is called hydration.

So SSR and SSG pages have a moment where you can see it but cannot press it. Hammer a button right after opening and nothing happens, then a little later it starts working — that is this window.

"Fast to show" and "fast to become usable" are two different things. What SSR and SSG shorten is the first one. Shortening the second means making the JavaScript that does the hooking up lighter.

HTML shown → JS loaded → wired up → usable

11 / 11

Wrapping up

The five things from this lesson.

  • HTML gets built in one of three places: CSR (the browser), SSR (the server, on every request), SSG (in advance)
  • You choose along a fast first paint, fresh data, load on the server, and whether you have to build again. No way of doing it comes first in everything
  • ISR, or regeneration, is the middle way: it keeps the speed of building in advance while cutting the staleness
  • The way of doing it can change from page to page. Decide one page at a time by asking "is this the same whoever looks?"
  • Going SSR does not make the data round trips go away. What it replaces is the first page only

And the one not to forget: which side does this code run on. The features the browser provides are not on the server, and secrets cannot live in the browser.

Next lesson we open up ② itself — the round trip that fetches data.