How to Implement Code Splitting and Lazy Loading in React
A step-by-step guide on how to reduce initial bundle size by dynamically importing components using React.lazy and Suspense.
Understand the Bundle Size Problem
By default, when you build a React app, all your JavaScript is bundled into one large file. The browser must download this entire file before anything renders. As your app grows, this file gets bigger and the initial page load gets slower. Code splitting breaks the bundle into smaller chunks that load on demand.
Understand Dynamic Imports
Modern JavaScript supports dynamic imports using the import function with parentheses. When bundlers like Webpack or Vite encounter a dynamic import, they automatically split that module into a separate chunk file. That chunk is only downloaded when the dynamic import is actually executed at runtime.
Use React.lazy to Lazy Load a Component
React.lazy accepts a function that returns a dynamic import of your component. Call React.lazy and pass it an arrow function that calls import with the component's file path. The result is a lazy component that React knows to load on demand. Only call React.lazy at the top level of a module, never inside another component.
Wrap Lazy Components with Suspense
Lazy loaded components cannot render instantly because they need to be downloaded first. Wrap any lazy component with React's Suspense component. Pass a fallback prop to Suspense with the UI you want to show while the lazy component is loading, typically a spinner or a skeleton screen.
Apply Lazy Loading to Routes
The most effective place to apply code splitting is at the route level. Each route represents a full page and users typically visit only a few pages per session. Make each page component lazy with React.lazy and wrap your router's Routes with a single Suspense boundary. Each page chunk now loads only when the user navigates to that route.
Place Suspense Boundaries Strategically
You can have multiple Suspense boundaries at different levels of the component tree. A Suspense boundary nearest to the lazy component shows its fallback while only that component loads. A Suspense boundary higher up catches multiple lazy components. Place boundaries where the loading experience makes the most sense from a UX perspective.
Preload Components Proactively
To improve perceived performance, you can trigger the load of a lazy component before the user navigates to it. On hover of a navigation link, call the dynamic import function directly without React.lazy. The browser starts downloading the chunk in the background. By the time the user clicks, the component may already be loaded.
Analyze the Bundle to Find Splitting Opportunities
Use tools like the Webpack Bundle Analyzer or Vite's built-in rollup visualizer to see a visual map of your bundle and identify large dependencies or components. Look for heavy third-party libraries used on specific pages, modal components that are rarely opened, and admin sections that most users never visit. These are prime candidates for lazy loading.
Ready to master this completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.

