Topic 48 of 54
Code Splitting with Suspense
Overview
By default, bundlers like Webpack or Vite package your entire React app into one massive JavaScript file. If your app is large, the user has to download 5MB of JS before seeing a single button. Code Splitting (using `React.lazy` and `<Suspense>`) allows you to chop that bundle up. You can delay downloading the code for specific components (like heavy charts or admin pages) until the user actually navigates to them.
Syntax
The user doesn't download the code for `HeavyChart` until they click the button. This drastically reduces the initial load time of the application.
Lazy Loading a Component
jsx
import { useState, lazy, Suspense } from 'react';
// 1. Import the component dynamically using React.lazy()
// This creates a separate JS file chunk during the build process
const HeavyChart = lazy(() => import('./components/HeavyChart'));
function Dashboard() {
const [showChart, setShowChart] = useState(false);
return (
<div>
<button onClick={() => setShowChart(true)}>Show Analytics</button>
{/* 2. Wrap the lazy component in <Suspense> */}
{/* 'fallback' is shown while the browser downloads the component's JS file over the network */}
{showChart && (
<Suspense fallback={<div>Loading chart data...</div>}>
<HeavyChart />
</Suspense>
)}
</div>
);
}Common Pitfalls
- Using `React.lazy` on small UI components like buttons. The overhead of network requests makes this slower. Only use it for massive components, specific routes, or rarely used features.
Interview Tips
- Route-based code splitting is the most impactful performance optimization you can make. Mentioning that you use `React.lazy` on your React Router `<Route>` definitions is a huge plus.
Real-World Example
Applying Code Splitting at the routing level so users only download the code for the specific page they are visiting.
example
jsx
const Home = lazy(() => import('./pages/Home'));
const Settings = lazy(() => import('./pages/Settings'));
function App() {
return (
<BrowserRouter>
{/* Suspense handles the loading state for ALL lazy routes inside it */}
<Suspense fallback={<GlobalSpinner />}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}