Table of Contents
- Introduction
- What is Code Splitting?
- Why Code Splitting Matters
- Understanding
React.lazy
- How to Use
React.lazy
andSuspense
- Code Splitting with Dynamic Imports
- Using Lazy Loading with React Router
- Handling Loading States with Fallbacks
- Error Handling with Suspense and Error Boundaries
- Advanced Code Splitting Strategies
- Best Practices
- Conclusion
1. Introduction
As React applications grow, the size of your JavaScript bundle grows as well. Users may face slower load times, especially on slower networks or devices. The solution is code splitting — a technique that allows you to break your bundle into smaller chunks and load them on demand.
React provides built-in support for lazy loading components using React.lazy()
and Suspense
. In this module, we’ll explore how to implement code splitting in real-world applications.
2. What is Code Splitting?
Code splitting is the process of splitting a large JavaScript bundle into smaller pieces that can be loaded on demand. It helps reduce the initial load time and improves perceived performance by deferring loading of non-essential parts of the app.
Modern bundlers like Webpack or Vite support this through dynamic import()
statements.
3. Why Code Splitting Matters
- Performance: Reduces initial page load time.
- Efficiency: Users only download code they need.
- UX Boost: Faster interaction and smoother transitions.
- Scalability: Makes large applications manageable.
4. Understanding React.lazy
React.lazy
lets you render a dynamic import as a regular component.
Syntax:
jsxCopyEditconst LazyComponent = React.lazy(() => import('./MyComponent'));
This doesn’t immediately fetch MyComponent.js
. It’s only loaded when the component is actually rendered.
5. How to Use React.lazy
and Suspense
React.lazy
must be wrapped in a <Suspense>
component, which handles the loading fallback:
jsxCopyEditimport React, { Suspense } from 'react';
const Settings = React.lazy(() => import('./Settings'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Settings />
</Suspense>
);
}
The fallback can be anything: a spinner, skeleton loader, shimmer effect, etc.
6. Code Splitting with Dynamic Imports
You can lazily load any module, not just React components:
jsCopyEditbutton.onclick = () => {
import('./analytics').then((module) => {
module.trackClick();
});
};
This creates a separate chunk for analytics.js
that is only loaded on user interaction.
7. Using Lazy Loading with React Router
When integrating with React Router v6, lazy load route components for better performance:
jsxCopyEditimport { Routes, Route } from 'react-router-dom';
const Home = React.lazy(() => import('./pages/Home'));
const About = React.lazy(() => import('./pages/About'));
function App() {
return (
<Suspense fallback={<p>Loading page...</p>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</Suspense>
);
}
This defers loading each page component until its route is visited.
8. Handling Loading States with Fallbacks
Use skeletons, spinners, or any UI as fallback content:
jsxCopyEdit<Suspense fallback={<Skeleton type="card" />}>
<LazyCard />
</Suspense>
Or define more specific loading states per route or component tree.
9. Error Handling with Suspense and Error Boundaries
Suspense
doesn’t catch loading errors. You must combine it with an Error Boundary:
jsxCopyEditclass ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
return this.state.hasError
? <div>Error loading component</div>
: this.props.children;
}
}
// Usage:
<ErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
</ErrorBoundary>
10. Advanced Code Splitting Strategies
- Per Route Splitting: Lazy load each page independently.
- Per Component Splitting: Split rarely used modals, admin tools, dashboards.
- Preload on Hover: Preload components on user intent: jsCopyEdit
import('./Modal');
- Bundle Analysis: Use tools like Webpack Bundle Analyzer to visualize splits.
11. Best Practices
- Don’t overuse lazy loading for tiny components — it may add overhead.
- Always provide meaningful fallbacks.
- Group related components in chunks when necessary.
- Use React Profiler to track performance improvements.
12. Conclusion
Code splitting is a powerful technique to make your React apps faster and more user-friendly. Using React.lazy
and Suspense
, you can load parts of your UI only when needed, improving the performance and user experience of your applications.