Paying for the whole menu to order chiya
A single-page app ships one big JavaScript bundle: the reviews widget, the admin dashboard, the map, the date picker — all downloaded, parsed and compiled before the first click works, even by someone who just wants to order chiya. The field guide's modularity chapter makes the point that JavaScript is byte-for-byte the most expensive thing a page loads, because it must also be parsed and run.
Two decisions control that cost. Code splitting decides *what* JavaScript loads and *when*. Rendering patterns decide *where* HTML is produced — in the browser, on a server per request, or ahead of time at build. Big apps get both right.
lazy, Suspense and preloading
import("./Reviews") (with parentheses) is a dynamic import: bundlers like Vite and webpack turn it into a separate chunk fetched only when that line runs. React.lazy(() => import("./Reviews")) turns it into a component whose code is loaded the first time it renders — lazy loading. While it loads, the nearest <Suspense fallback> shows instead.
function lazyWithPreload(factory) {
let promise = null;
const load = () => (promise ??= factory());
const Component = lazy(load);
Component.preload = load;
return Component;
}
const Reviews = lazyWithPreload(() => import("./Reviews"));
<button onMouseEnter={Reviews.preload} onFocus={Reviews.preload} onClick={open}>Reviews</button>- Split by route first: each page becomes a chunk — the biggest win for the least effort.
- Split heavy, rarely used widgets: editors, charts, maps, modals.
- Don't split tiny components: every chunk costs a request.
- <link rel="preload"> fetches what this page needs soon; <link rel="prefetch"> fetches what the *next* page will probably need, at low priority — both from the Learning Patterns book's loading chapter.