Code Splitting: Optimize Bundle Size with Dynamic Imports
Code splitting breaks your JavaScript bundle into smaller chunks that load on demand. It dramatically reduces initial load time by shipping only the code required for the current view. Use dynamic imports (`import()`) with React.lazy() and Suspense for seamless integration.
Instead of packing everything for every trip (large initial bundle), pack only what you need for today's journey (route) and open side pockets (heavy components) only when required. Dynamic imports let you unzip those pockets on demand.
1Route-Based Splitting
Automatically split by page/route. Each route becomes its own chunk, loaded only when the user navigates there.
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
<Suspense fallback={<Loading />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>2Component-Based & Dynamic Imports
Split heavy components (charts, modals, editors) and load them conditionally on interaction or visibility.
3Vendor Splitting
Separate third-party libraries into their own chunk for better long-term caching since they change less frequently.
| Property | Route-Based | Component-Based |
|---|---|---|
| Cons | Navigation delay possible | Requires loading states, More manual |
| Pros | Natural boundaries, Easy with React Router / Next.js, Good for large apps | Fine-grained control, Load only when needed |
| Best For | Multi-page applications | Heavy modals, charts, editors |
Route-Based
Cons
Navigation delay possible
Pros
Natural boundaries, Easy with React Router / Next.js, Good for large apps
Best For
Multi-page applications
Component-Based
Cons
Requires loading states, More manual
Pros
Fine-grained control, Load only when needed
Best For
Heavy modals, charts, editors
Common questions
- ›“How do you implement code splitting in a React app?”
- ›“What are the trade-offs of lazy loading?”
- ›“How does dynamic import() work under the hood?”
- ›“When should you split code vs keep it together?”
What interviewers look for
- Practical use of React.lazy() + Suspense
- Understanding of bundle impact and user experience
- Awareness of loading states and error boundaries
- Data-driven approach (measure before/after)
Short answer (60 sec)
Use dynamic imports (`import()`) and React.lazy() to split code by routes and heavy components. Wrap lazy components in Suspense with meaningful fallbacks. This reduces initial bundle size and improves LCP.
Detailed answer (senior level)
Route-based splitting gives natural chunking for navigation. Component-based splitting targets heavy features like charts or modals. Vendor splitting improves cache longevity. Combine with prefetching on hover and proper loading/error states. Always measure bundle sizes and real-user metrics — splitting too aggressively can hurt navigation experience.
- Lazy loading critical above-the-fold components
- Forgetting Suspense fallbacks (blank screens)
- Not handling errors in dynamic imports
- Over-splitting into tiny chunks (too many requests)
- Ignoring prefetching for likely next routes
- ✓Code splitting reduces initial bundle size and improves LCP
- ✓Use React.lazy() + Suspense for easy route/component splitting
- ✓Dynamic imports enable conditional and on-demand loading
- ✓Separate vendor code for better caching
- ✓Always provide loading states and error boundaries
- ✓Measure bundle analyzer output and real-user performance
- ✓Balance splitting with user-perceived latency