A page drawn on the server

Pinch or Ctrl+scroll to zoom; the text is selectable. Source · TheYard

A page drawn on the server: from the address through the edge, the rendering service and the API to the HTML the browser paints, and then the takeover A page drawn on the server: the first load, then the takeover Every box is a file; the path under each title is where that step lives. The service in render/ is a client of the API, like a browser; the API draws nothing and does not know it exists. The first load: drawn once, on the server, for this request From the address to the painted page. The API is only read; a read that misses the deadline is left to the browser. The takeover: React attaches, it does not redraw Hydration, in React's word. One mismatch and the markup is thrown away. The address the visitor's browser theyard.stevenstout.biz/?view=inventory, ?vehicle= or ?doc=. A page is the bare path with its query; the bundle, the photographs and /api are other paths, which never come this way. GET /?view=inventory The edge edge/_redirects Netlify matches the bare path on either name and rewrites it, query and all, to the rendering service as that site: /site/sql or /site/cosmos. Everything else goes to that site's API as before. 200 rewrite to /site/sql?view=inventory The page and the build render/page.ts The service reads index.html and /api/version from the API it draws for, kept fifteen seconds. The page names the bundle that API serves; the service draws only when the API runs the build the service was made from, and during a roll it sends the API's page untouched for the browser to draw. the API runs the same build: draw One loader per view, under one deadline render/loaders.ts Who is signed in (the cookie forwarded, nothing else) and the build for the footer on every page; on an inventory or vehicle address the first page of the list with its facets; on ?vehicle= the vehicle; on ?doc= the document, rendered with the same Markdown code the browser uses. All at once under 2.5 seconds; a read that fails or runs late is left to the browser. the reads, all at once The draw, and the stream render/render.ts, src/app/entry-server.tsx Everything above #root leaves at once, before any read has answered, so the browser starts on the stylesheet, the font and the bundle. Then #root with the site drawn by React's server renderer from what the loaders read; then the first load, that same data as JSON beside #root with every < escaped; then the rest of the page. the top first, then the drawing, then the first load The browser paints the visitor's browser The HTML arrives with the view in it, and the browser shows the inventory, the vehicle or the document before any script has run. Measured on 8 October: the inventory's speed index on a phone 3.5 s where it read 5.8 drawn in the browser. The bundle arrives index.html, the API's own page The script the page named, already downloading while the service was drawing. Nothing in it is special to a drawn page. script runs The first load is read src/app/mount.tsx, src/app/firstLoad.ts #root says data-drawn="server" and the JSON beside it says which address it was drawn for. If it matches the address bar, hydrateRoot; otherwise the page is drawn from nothing, as it always was. the address matches: hydrateRoot Every hook starts from it src/hooks/useFirstLoad.ts Each hook that used to start empty (the address, the list, the vehicle, the account, the build, the clock) starts from the first load instead, so the browser's first draw is the server's draw, byte for byte. same markup on both sides The four differences, answered src/hooks/useMediaQuery.ts, src/library/DocDialog.tsx The clock: the browser counts down from the time the server drew at, then ticks. The time zone: UTC until the page is live, then the viewer's. The window's width: "does not match" until the page is live, then the real answer. The document window: drawn open where the modal stands, then opened again as a modal. after the takeover, each changes once Live src/app/TheYard.tsx React has attached its handlers to the markup it found. A click, a filter, a bid: the site from here is the site it always was, reading /api as before. tests/e2e/drawn.spec.ts opens every drawn view in Chrome and fails on a hydration error or a window that moved. the page is on screen while the script is still arriving; the dashed line is the takeover beginning Measured on the service alone in Docker: the top of the page in 7 to 9 ms, the drawn inventory in 105 ms at the median. Through the domain the top and the drawing arrive together, because the edge in use today holds a proxied answer until it has all of it. Source: docs/images/server-page.svg in the repository, drawn by docs/images/server-page.mjs and redrawn when a step moves.