Code Splitting and Lazy Loading
React.lazy
import { lazy, Suspense } from 'react';
// Lazy load components
const Dashboard = lazy(() => import('./Dashboard'));
const Profile = lazy(() => import('./Profile'));
const Settings = lazy(() => import('./Settings'));
function App() {
return (
<Suspense fallback={<LoadingSpinner />}>
<Routes>
<Route path='/dashboard' element={<Dashboard />} />
<Route path='/profile' element={<Profile />} />
<Route path='/settings' element={<Settings />} />
</Routes>
</Suspense>
);
}
Route-Based Code Splitting
const routes = [
{
path: '/',
component: lazy(() => import('./pages/Home')),
},
{
path: '/about',
component: lazy(() => import('./pages/About')),
},
{
path: '/products',
component: lazy(() => import('./pages/Products')),
},
];
function App() {
return (
<Suspense fallback={<PageLoader />}>
<Routes>
{routes.map(({ path, component: Component }) => (
<Route key={path} path={path} element={<Component />} />
))}
</Routes>
</Suspense>
);
}
Dynamic Import
function loadComponent(componentName: string) {
return lazy(() => import(`./components/${componentName}`));
}
// Preload on hover
function ProductCard({ product }) {
const handleMouseEnter = () => {
import('./ProductModal'); // Preload
};
return <div onMouseEnter={handleMouseEnter}>{product.name}</div>;
}
Best Practices
- Split by routes - Each route gets own bundle
- Split by features - Large features in separate bundles
- Preload on interaction - Load before needed
- Show loading states - Use Suspense fallback
- Error boundaries - Handle loading failures