Clean β’ Professional
When building React apps, performance is everything β especially for users on slower networks. One of the most effective ways to make your app load faster is through code splitting and bundle optimization.
By default, tools like Create React App or Vite bundle all your JavaScript into a single large file. But loading one big file slows down the initial page load. Code splitting helps by breaking your app into smaller, manageable chunks that are loaded only when needed.
Code splitting is the process of dividing your appβs JavaScript bundle into smaller chunks so that users only download what they need for the current view.
Instead of loading the entire app upfront, React dynamically loads parts of it β such as specific components, routes, or libraries β when they are actually required.
This results in:
Imagine your app has multiple pages β Dashboard, Profile, Settings, and Reports.
Without code splitting, your user must download all components at once, even if they only visit the Dashboard.
With code splitting, React loads only the Dashboard bundle first. Other parts are fetched on demand when the user navigates to them.
This significantly improves First Contentful Paint (FCP) and Time to Interactive (TTI) β two key web performance metrics for SEO and UX.
React provides a built-in function, React.lazy(), for lazy loading components. It works with dynamic imports and is typically combined with <Suspense> for handling loading states.
Example:
import React, { Suspense, lazy } from "react";
const Dashboard = lazy(() => import("./Dashboard"));
const Settings = lazy(() => import("./Settings"));
function App() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
<Settings />
</Suspense>
</div>
);
}
export default App;
lazy() dynamically imports the components only when needed.<Suspense> shows a fallback (like a spinner or βLoadingβ¦β message) while the component is being loaded.For larger apps, route-based code splitting is the best approach. Each page (or route) can be lazy-loaded separately.
Example:
import React, { Suspense, lazy } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
const Home = lazy(() => import("./pages/Home"));
const About = lazy(() => import("./pages/About"));
const Contact = lazy(() => import("./pages/Contact"));
function App() {
return (
<Router>
<Suspense fallback={<p>Loading Page...</p>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</Router>
);
}
export default App;
Each route is bundled into a separate chunk and fetched only when the user navigates there.
You can also split code manually using dynamic imports.
Example:
async function loadHelper() {
const module = await import("./utils/helper");
module.default();
}
This ensures that the helper file is downloaded only when the function is called β not when the app loads.
After splitting your code, you should further optimize bundles using these techniques:
a. Tree Shaking
import { usedFunc } from "./utils"; // Only 'usedFunc' will be included
b. Minification
c. GZIP / Brotli Compression
d. Image & Asset Optimization
Use modern formats like WebP and AVIF, and leverage lazy loading for images to improve initial page speed.
To find out whatβs taking up space in your bundle, use a bundle analyzer.
npm install source-map-explorer --save-dev
Then run:
npm run build
npx source-map-explorer 'build/static/js/*.js'
Youβll see a visual breakdown of whatβs inside your bundle.
Use the plugin:
npm install rollup-plugin-visualizer --save-dev
Then analyze:
npm run build
npm run analyzeΒ