Code Splitting
Load features only when needed.
When you build a React app for production, it generates:
Out of these, JavaScript is the biggest performance bottleneck.
Large JavaScript affects multiple stages:
Instead of loading everything at once:
This is called Code Splitting
Used for heavy components (charts, editors, maps)
import { lazy, Suspense } from "react";
const HeavyChart = lazy(() => import("./HeavyChart"));
function Dashboard() { return ( <Suspense fallback={<p>Loading chart...</p>}> <HeavyChart /> </Suspense> );}lazy() → dynamically imports componentSuspense → shows fallback while loadingBest optimization for real apps.
import { lazy, Suspense } from "react";import { Routes, Route } from "react-router-dom";
const Home = lazy(() => import("./pages/Home"));const Settings = lazy(() => import("./pages/Settings"));const Reports = lazy(() => import("./pages/Reports"));
export default function AppRoutes() { return ( <Suspense fallback={<p>Loading page...</p>}> <Routes> <Route path="/" element={<Home />} /> <Route path="/settings" element={<Settings />} /> <Route path="/reports" element={<Reports />} /> </Routes> </Suspense> );}Without splitting:
main.js (very large file with everything)With splitting:
main.jshome.chunk.jsreports.chunk.jssettings.chunk.jsBrowser loads only required chunks
Vite already splits code, but you can control grouping.
// vite.config.jsexport default { build: { rollupOptions: { output: { manualChunks: { reactVendor: ["react", "react-dom", "react-router-dom"], chartVendor: ["chart.js"], }, }, }, },};Code Splitting
Load features only when needed.
Tree Shaking
Import only required functions from libraries.
Image Optimization
Use WebP/AVIF and responsive images.
Memoization
Prevent unnecessary re-renders.
Virtualization
Render only visible items in large lists.
Caching
Cache static assets effectively.
Tools:
React.memouseMemouseCallbackUse:
Even if network is fast:
Performance = Network + CPU + Rendering