intermediate
Code splitting
Split routes, heavy widgets, and rarely used features so initial navigation loads only what the user needs now.
Code splitting breaks the application into chunks loaded on demand—by route, feature, or heavy library—so the initial navigation ships less JavaScript.
const AdminPanel = lazy(() => import('./AdminPanel'));
<Route path="/admin" element={
<Suspense fallback={<Spinner />}>
<AdminPanel />
</Suspense>
} />
| Split boundary | Good fit | |----------------|----------| | Route | Dashboard vs marketing site | | Feature flag | Beta editor not needed at first paint | | Heavy lib | Charting, PDF, rich text editor |
Balance splitting against **request waterfalls**: too many tiny chunks increase RTT overhead. Prefetch likely next routes after idle. In Next.js, prefer framework route-based splitting plus `dynamic()` for client-only widgets.
On interviews: route vs component splitting; Suspense boundaries; prefetch strategies; how splitting interacts with SSR/hydration cost.
Common pitfalls: splitting everything into micro-chunks; lazy-loading above-the-fold content; missing error boundaries on lazy routes.
The trade-off is smaller initial bundle versus more network round trips and loading states.
Checklist:
- Split at route and rare-feature boundaries.
- Prefetch high-probability next routes.
- Keep critical path chunks minimal.
- Measure waterfall in DevTools Network.