Large JavaScript bundles can slow down your application. When too much code is loaded at once, users wait longer for the first paint and pages feel less responsive. Search engines may also rank slow sites lower in results.

Lazy loading helps solve this problem by breaking up your code into smaller chunks and loading them when needed.

This guide walks you through lazy loading in React and Next.js. By the end, you’ll know when to use it. React.lazy, next/dynamicand Suspenseand you’ll have working examples that you can copy and adapt to your own projects.

Table of Contents

What is lazy loading?

Lazy loading is a performance technique that delays loading code until it is needed. Instead of loading your entire app at once, you break it up into smaller parts. The browser only downloads a portion when the user navigates to that path or interacts with that feature.

Benefits include:

  • Faster initial load: Smaller first bundle means faster time to interactive

  • Improved Core Web Vitals: Greatest material-rich paint and improves total blocking time.

  • Low bandwidth: Users download only what they use.

In React, you achieve this with dynamic imports. React.lazy() or Next.js next/dynamic.

Conditions

Before you proceed, you must:

  • Basic familiarity with React (components, hooks, state)

  • Node.js installed (version 18 or later recommended)

  • A React app (Create React App or White) or a Next.js app (for Next.js instances)

For React examples, you can use the Create React app or Vite. For Next.js instances, use App Router (Next.js 13 or later).

How to use React.lazy For code distribution

React.lazy() Lets you define a component as a dynamic import. React will only load this component the first time it is rendered.

React.lazy() Expects a function that returns dynamic. import(). Imported modules should use the default export.

Here is a basic example:

import  from 'react';

const HeavyChart = lazy(() => import('./HeavyChart'));
const AdminDashboard = lazy(() => import('./AdminDashboard'));

function App() 
      return this.props.fallback 

If you use named exports, you can map them to a default export:

const ComponentWithNamedExport = lazy(() =>
  import('./MyComponent').then((module) => ( 

Something went wrong.

; )) );

You can also name snippets for easier debugging in the browser:

const HeavyChart = lazy(() =>
  import(/* webpackChunkName: "heavy-chart" */ './HeavyChart')
);

React.lazy() Alone is not enough. You have to wrap the slow ingredients. Suspense So React knows what to show when loading.

How to use Suspense with the React.lazy

Suspense A React component that displays a fallback UI while its children are loading. Works with it. React.lazy() To handle the loading state of dynamically imported components.

Wrap your lazy ingredients. Suspense and provide a fallback Support:

import  

Something went wrong.

; from 'react'; const HeavyChart = lazy(() => import('./HeavyChart')); const AdminDashboard = lazy(() => import('./AdminDashboard')); function App() { return (

Loading chart...

}> Loading dashboard...