Demo
Northstar Supply
A small industrial-tools store written as an ordinary React 18 app (function components,
four contexts, hooks, lists, useId, forms), server-rendered three ways. The app is known ahead of
time and the request data is not. The two specialized renderers produce the same bytes as
renderToString, in a fraction of the time.
React
renderToString
ReactDOMServer.renderToString on the bundled app (dist/app.js). The reference output.
Open the store →
Prepack
Prepack-specialized
dist/render-prepack.js: the revived Prepack partially evaluates React's server renderer together with the app for a data schema. No React at runtime; data outside the schema falls back to React.
Open the store →
Hybrid
Hybrid (traced templates)
dist/render-hybrid.js: templates learned by tracing the real app under React, with runtime guards; a failed guard renders that request with React.
Open the store →
Open the store Compare render times
Using the demo
- Every store page exists in all three renderers:
/northstar/react/search?q=drill,/northstar/prepack/search?q=drilland/northstar/hybrid/search?q=drillreturn the same HTML. The bar at the top switches renderer for the current page. - The store is fully server-rendered and works without JavaScript: search, category pages, sorting and filters, pagination (or View all for the whole catalog, ~300 KB of HTML), product pages, a cookie-based cart and a sign-in stub. A light/dark theme switch is in the header.
- The bar shows the time spent in the render call alone (
performance.now()around it), and whether a specialized renderer handled the request itself or fell back to React. The same number is in theServer-Timingresponse header.
How the specialized renderers are made
- Prepack: the revived Prepack runs a small port of React 18's server renderer together with the app, with the request data abstract (a schema inferred from training requests). React and the component tree fold away, leaving string concatenation, loops and escaping. A schema check guards each call; data outside the schema is rendered with React.
- Hybrid: the app runs under the real React on training requests while every operation is traced. Each component becomes a template of constant HTML chunks and slots, with a guard for every branch and type the trace relied on. A failed guard renders that request with React.
Both are built from the same bundle (dist/app.js) and checked byte-for-byte against
renderToString on 600 live-store requests and a 500-input random benchmark corpus. Source:
jlongster/northstar-supply.