Code Splitting & <Suspense>
How to dramatically improve your app's load time by splitting your JavaScript bundle and loading components only when needed.
The Monolith Problem
By default, tools like Webpack or Vite bundle your entire React application—every page, every modal, every heavy chart library—into a single massive bundle.js file.
When a user visits your homepage, their browser has to download, parse, and execute that entire 5MB file before they can click a single button. This results in terrible Time to Interactive (TTI) scores.
Code Splitting is the process of breaking that monolith into smaller, on-demand chunks.
React.lazy() and <Suspense>
React provides a built-in way to dynamically import components using React.lazy(). Instead of importing a heavy component at the top of the file, you tell React to only fetch its JavaScript code when it's actually rendered on the screen.
While the browser is fetching that new JavaScript chunk over the network, React needs something to show the user. This is what <Suspense> does: it displays a fallback UI (like a skeleton loader or spinner) while the inner component's code is downloading.
Dynamic Imports in Action
First, dynamically import the component:
const HeavyChart = React.lazy(() => import('./HeavyChart'));
Then, wrap it in a Suspense boundary when you render it:
<Suspense fallback={<Spinner />}>
<HeavyChart data={data} />
</Suspense>
If the user never navigates to the page with the chart, they never pay the performance penalty of downloading the chart library's JavaScript!
The Network Pipe
Interact with the diagram below to simulate a user loading an application over a 3G connection. Compare downloading the monolithic 5MB bundle vs loading just the 500KB shell instantly, and deferring the rest.
Interactive Diagram: The Network Pipe
Simulating a Slow 3G Connection
Analytics Dashboard
User stares at a blank screen until the entire 5MB file downloads.
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Code splitting breaks your large
bundle.jsinto smaller, on-demand files. React.lazy()allows you to dynamically import a component.<Suspense>provides the fallback UI (loading state) while the code downloads.- Code-split at the Route level first, then on massive isolated components (like complex charts or rich text editors).
- Modern React also uses Suspense for data fetching, not just code fetching.
Done with this concept?
Mark it complete to track your progress. No login needed.