Script Valley
React.js: Complete Course
React Router and NavigationLesson 5.4

Code splitting and lazy loading routes in React

React.lazy, Suspense fallback, dynamic import, route-based code splitting, bundle size benefits, Suspense boundaries, loading states

Lazy Loading Routes for Performance

By default, Vite/webpack bundles all your code into one file. For large apps, this means users download everything upfront — even routes they may never visit. React.lazy splits routes into separate chunks loaded on demand.

Implementing Lazy Routes

import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

// Dynamic imports — these create separate bundles
const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div>Loading...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/dashboard" element={<Dashboard />} />
          <Route path="/settings" element={<Settings />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Suspense renders the fallback while the lazy component loads. Place the Suspense boundary at the right level — wrapping only the route area shows the loading state without unmounting the entire page. Use a skeleton or spinner component as the fallback for better UX.

Up next

React Router data APIs: loaders and actions

Sign in to track progress