Code splitting

3 snippets across 2 stacks - React, JavaScript

REReact

Suspense & Lazy Loading

RE · Patterns
Syntax
const LazyComponent = React.lazy(() => import('./Component'));

<Suspense fallback={<Loading />}>
  <LazyComponent />
</Suspense>
Example
import { lazy, Suspense, useState } from 'react';

const AdminPanel = lazy(() => import('./AdminPanel'));
const UserDashboard = lazy(() => import('./UserDashboard'));

function App({ role }) {
  return (
    <Suspense fallback={<div className="spinner">Loading...</div>}>
      {role === 'admin' ? <AdminPanel /> : <UserDashboard />}
    </Suspense>
  );
}

Note React.lazy only works with default exports. For named exports, create an intermediate module that re-exports as default. Suspense can also wrap components that use the use() hook to read promises in React 19.

Code Splitting by Route

RE · Performance
Syntax
const Page = lazy(() => import('./Page'));
<Suspense fallback={<Spinner />}>
  <Page />
</Suspense>
Example
import { lazy, Suspense } from 'react';

const Home = lazy(() => import('./pages/Home'));
const Products = lazy(() => import('./pages/Products'));
const Account = lazy(() => import('./pages/Account'));

function AppRouter() {
  const [route, setRoute] = useState('home');

  return (
    <nav>
      <button onClick={() => setRoute('home')}>Home</button>
      <button onClick={() => setRoute('products')}>Products</button>
      <button onClick={() => setRoute('account')}>Account</button>

      <Suspense fallback={<div className="page-loader">Loading page...</div>}>
        {route === 'home' && <Home />}
        {route === 'products' && <Products />}
        {route === 'account' && <Account />}
      </Suspense>
    </nav>
  );
}

Note Route-based code splitting gives the biggest bundle size reduction because entire page components and their dependencies are loaded on demand. Place the Suspense boundary around the lazy components, not the entire app.

JSJavaScript

Dynamic Import

JS · Modules
Syntax
const module = await import("./module.js");
Example
async function loadEditor() {
  const { EditorView } = await import("./editor.js");
  return new EditorView(document.getElementById("editor"));
}

// Conditional loading
if (needsCharting) {
  const { renderChart } = await import("./charts.js");
  renderChart(data);
}

Note Returns a promise that resolves to the module namespace. Ideal for code-splitting, lazy loading, and conditional imports. Works at runtime, not just at the top of a file.

Frequently asked questions

How does React handle code splitting?
This task is covered in 2 stacks on this page: React, JavaScript. The "Suspense & Lazy Loading" snippet in React uses `const LazyComponent = React.lazy(() => import('./Component'));`.
Which code does the React example use?
The "Suspense & Lazy Loading" snippet uses `const LazyComponent = React.lazy(() => import('./Component'));`, from the Patterns section of the React cheat sheet.
Which stacks cover "code splitting" on this page?
React, JavaScript. Together they hold 3 copy-ready snippets for this task.
Is there anything to watch out for?
Yes. For "Suspense & Lazy Loading": React.lazy only works with default exports. For named exports, create an intermediate module that re-exports as default. Suspense can also wrap components that use the use() hook to read promises in React 19.