All topics
Performanceintermediate

Code Splitting with React.lazy and Suspense

Learn the general mechanism of React.lazy and Suspense for splitting any part of the component tree into separately loaded chunks.

Beyond route-level splitting, React.lazy and <Suspense> can defer loading any sufficiently large or rarely-used component — a rich text editor, a complex chart, a modal only shown after a specific user action — until it's actually needed, rather than including it in the main bundle every user downloads regardless of whether they ever trigger it.

It's like keeping specialized tools in a closet instead of a work apron everyone wears all day — you fetch the specific tool (component) from the closet (a separate chunk) only at the moment a task actually calls for it, rather than every worker carrying every possible tool around all day just in case.

Key Concepts

1
React.lazy(() => import('./HeavyComponent')) returns a component that transparently triggers the dynamic import on first render and suspends until the module is available. Any <Suspense fallback={...}> boundary above it in the tree catches that suspended state and displays the fallback (commonly a spinner or skeleton) until the import resolves, then swaps in the real component.
React.lazy(() => import('./HeavyComponent'))<Suspense fallback={...}>
2
A single <Suspense> boundary can wrap multiple lazy components, and if several of them suspend at once, React shows the shared fallback until all of them are ready, rather than each showing its own independent fallback — placing boundaries at different granularities (one big boundary vs. several small ones) is a deliberate design decision about how loading states are grouped and perceived.
<Suspense>
3
Interviewers ask candidates to identify good candidates for lazy-loading beyond just routes — commonly modals, below-the-fold widgets, and heavy third-party library integrations — and to reason about Suspense boundary placement tradeoffs: a single top-level boundary is simpler but produces a coarser loading experience, while granular boundaries give smoother per-section loading at the cost of more boundaries to manage.