What is Code-Splitting?
Code-splitting is a technique that breaks a large JavaScript bundle into smaller chunks. Instead of loading the entire application at once, it loads only the necessary code when required.
Why is this important?
- Improves Initial Load Time: The browser doesn’t have to download a huge JS file at once.
- Faster Performance: Unused code is not loaded until needed, reducing memory usage.
- Optimized User Experience: Users interact with the app without waiting for unnecessary components to load.
How Code-Splitting Works in React
React automatically supports code-splitting through dynamic imports and React.lazy
.
- Instead of bundling everything in a single monolithic JavaScript file, the app splits into separate bundles (chunks).
- These bundles are loaded on demand when a user navigates to a new page or interacts with a specific component.
lazy
lets you defer loading component’s code until it is rendered for the first time.
const SomeComponent = lazy(load)
Call lazy
outside your components to declare a lazy-loaded React component:
import { lazy } from 'react'; const MarkdownPreview = lazy(() => import('./MarkdownPreview.js'));
Parameters
load
: A function that returns a Promise or another thenable (a Promise-like object with athen
method). React will not callload
until the first time you attempt to render the returned component. After React first callsload
, it will wait for it to resolve, and then render the resolved value’s.default
as a React component. Both the returned Promise and the Promise’s resolved value will be cached, so React will not callload
more than once. If the Promise rejects, React willthrow
the rejection reason for the nearest Error Boundary to handle.
Returns
lazy
returns a React component you can render in your tree. While the code for the lazy component is still loading, attempting to render it will suspend. Use <Suspense>
to display a loading indicator while it’s loading.
Example: Lazy Loading a Component
import React, { lazy, Suspense } from "react"; // Lazy load the Home component const Home = lazy(() => import("./Home")); const App: React.FC = () => { return ( <div> <h1>Welcome to My App</h1> {/* Wrap with Suspense to show fallback while loading */} <Suspense fallback={<h2>Loading Home...</h2>}> <Home /> </Suspense> </div> ); }; export default App;
Now, Home
loads only when needed!
lazy(() => import("./Home"))
→ Dynamically imports theHome
component.Suspense
withfallback={<h2>Loading Home...</h2>}
→ Displays a loading message untilHome
is ready.
Handling Multiple Lazy Components
You can use React.lazy
to load multiple components separately.
import React, { lazy, Suspense } from "react"; // Lazy load multiple components const Home = lazy(() => import("./Home")); const About = lazy(() => import("./About")); const App: React.FC = () => { return ( <div> <h1>Welcome to My App</h1> <Suspense fallback={<h2>Loading components...</h2>}> <Home /> <About /> </Suspense> </div> ); }; export default App;
Both Home
and About
will load separately, reducing initial load time.
Using React.lazy
with React Router
When using React Router
, you can lazy load routes dynamically, so they only load when accessed.
import React, { lazy, Suspense } from "react"; import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom"; // Lazy load components const Home = lazy(() => import("./Home")); const About = lazy(() => import("./About")); const App: React.FC = () => { return ( <Router> <nav> <Link to="/">Home</Link> | <Link to="/about">About</Link> </nav> <Suspense fallback={<h2>Loading page...</h2>}> <Routes> <Route path="/" element={<Home />} /> <Route path="/about" element={<About />} /> </Routes> </Suspense> </Router> ); }; export default App;
Now, pages load only when visited, improving performance.