Lesson 35 +10 XP

Code-Splitting & React.lazy

Code-Splitting & React.lazy

As a React application grows, the production JavaScript bundle size can become very large, resulting in slow initial page load times over slow network connections. Code-splitting breaks your JavaScript bundle into smaller chunks loaded on-demand.

Dynamic Imports with React.lazy

React.lazy lets you render a dynamically imported component as a regular component. It defers loading the component code bundle until it is actually rendered on screen.

import React, { Suspense } from 'react';

// Dynamically import component (code-split into separate JS chunk)
const HeavyChartComponent = React.lazy(() => import('./HeavyChartComponent'));

function Dashboard() {
  const [showChart, setShowChart] = useState(false);

  return (
    <div>
      <h1>Analytics Dashboard</h1>
      <button onClick={() => setShowChart(true)}>Load Chart</button>

      {showChart && (
        // Suspense displays fallback UI while HeavyChartComponent bundle downloads
        <Suspense fallback={<div>Loading Chart Component...</div>}>
          <HeavyChartComponent />
        </Suspense>
      )}
    </div>
  );
}

The <Suspense> Component

Lazy-loaded components MUST be rendered inside a <Suspense> boundary. The Suspense component accepts a fallback prop (JSX element like a spinner or skeleton loader) that displays while the child bundle is downloading over the network.

Route-Based Code-Splitting

The most strategic place to introduce code-splitting is at the application route level.

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

const Home = React.lazy(() => import('./routes/Home'));
const Profile = React.lazy(() => import('./routes/Profile'));
const Settings = React.lazy(() => import('./routes/Settings'));

function AppRoutes() {
  return (
    <BrowserRouter>
      <Suspense fallback={<div className="spinner">Loading Page...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/profile" element={<Profile />} />
          <Route path="/settings" element={<Settings />} />
        </Routes>
      </Suspense>
    </BrowserRouter>
  );
}

Summary & TL;DR

  • Code-splitting breaks large JS bundles into smaller chunks loaded on-demand.
  • React.lazy(() => import('./Component')) dynamically imports components.
  • Lazy components MUST be wrapped inside a <Suspense fallback={<Loader />}> boundary to display fallback UI while loading.
  • Route-based code splitting is best practice for optimizing initial page load speed.