Loading lessons...
Code-Splitting & React.lazy
Code-Splitting & React.lazy
As a React application grows, the production JavaScript bundle size can become very large, resulting in slow initial page load times over slow network connections. Code-splitting breaks your JavaScript bundle into smaller chunks loaded on-demand.
Dynamic Imports with React.lazy
React.lazy lets you render a dynamically imported component as a regular component. It defers loading the component code bundle until it is actually rendered on screen.
import React, { Suspense } from 'react';
// Dynamically import component (code-split into separate JS chunk)
const HeavyChartComponent = React.lazy(() => import('./HeavyChartComponent'));
function Dashboard() {
const [showChart, setShowChart] = useState(false);
return (
<div>
<h1>Analytics Dashboard</h1>
<button onClick={() => setShowChart(true)}>Load Chart</button>
{showChart && (
// Suspense displays fallback UI while HeavyChartComponent bundle downloads
<Suspense fallback={<div>Loading Chart Component...</div>}>
<HeavyChartComponent />
</Suspense>
)}
</div>
);
}
The <Suspense> Component
Lazy-loaded components MUST be rendered inside a <Suspense> boundary. The Suspense component accepts a fallback prop (JSX element like a spinner or skeleton loader) that displays while the child bundle is downloading over the network.
Route-Based Code-Splitting
The most strategic place to introduce code-splitting is at the application route level.
import React, { Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
const Home = React.lazy(() => import('./routes/Home'));
const Profile = React.lazy(() => import('./routes/Profile'));
const Settings = React.lazy(() => import('./routes/Settings'));
function AppRoutes() {
return (
<BrowserRouter>
<Suspense fallback={<div className="spinner">Loading Page...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/profile" element={<Profile />} />
<Route path="/settings" element={<Settings />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Summary & TL;DR
- Code-splitting breaks large JS bundles into smaller chunks loaded on-demand.
React.lazy(() => import('./Component'))dynamically imports components.- Lazy components MUST be wrapped inside a
<Suspense fallback={<Loader />}>boundary to display fallback UI while loading. - Route-based code splitting is best practice for optimizing initial page load speed.