惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 最新话题
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
PCI Perspectives
PCI Perspectives
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Heimdal Security Blog
S
Security @ Cisco Blogs
N
News | PayPal Newsroom
J
Java Code Geeks
罗磊的独立博客
Security Archives - TechRepublic
Security Archives - TechRepublic
N
News and Events Feed by Topic
V
V2EX
WordPress大学
WordPress大学
Google Online Security Blog
Google Online Security Blog
N
News and Events Feed by Topic
www.infosecurity-magazine.com
www.infosecurity-magazine.com
月光博客
月光博客
AI
AI
小众软件
小众软件
The GitHub Blog
The GitHub Blog
MongoDB | Blog
MongoDB | Blog
A
Arctic Wolf
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
美团技术团队
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tailwind CSS Blog
S
Schneier on Security
博客园 - 三生石上(FineUI控件)
F
Full Disclosure
B
Blog RSS Feed
Forbes - Security
Forbes - Security
S
SegmentFault 最新的问题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
云风的 BLOG
云风的 BLOG
Jina AI
Jina AI
Cisco Talos Blog
Cisco Talos Blog
U
Unit 42
Project Zero
Project Zero
H
Hacker News: Front Page
Y
Y Combinator Blog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
The Cloudflare Blog
大猫的无限游戏
大猫的无限游戏
S
Secure Thoughts
The Hacker News
The Hacker News
Microsoft Azure Blog
Microsoft Azure Blog

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

Learn Command Line Interface (CLI) Development with Dart: From Zero to a Fully Published Developer Tool How to Bypass Cloud SMTP Restrictions Using Brevo and HTTP APIs How to Build a Live Options Database in Python – A Complete Guide How to Migrate to S3 Native State Locking in Terraform How to Use SCons to Build Software Projects [Full Handbook] How to Run Open Source LLMs Locally and in the Cloud QuRT: The Real-Time OS Inside Your Phone's Processor [Full Handbook] The Real Infrastructure Behind Remote Work (It’s Not Just Wi-Fi) The Lithography Handbook: Machines, Markets, and the Next Wave of Semiconductor Startups ITCM vs DTCM vs DDR: Embedded Memory Types Explained [Full Handbook] AI Paper Review: Improving Language Understanding by Generative Pre-Training (GPT-1) How to Build a Market Research Copilot with MCP and Python [Full Handbook] How to Build a Scoped Note-Taking API with Django Rest Framework and SimpleJWT The Complete SOC 2 Type II Implementation Handbook for Engineers: A Month-by-Month Roadmap with Real Commands Mastering the JavaScript Event Loop Data Science Insights: Why the Mean Lies When Handling Messy Retail Data How to Build High-Ranking SEO Landing Page How to Query Data in DynamoDB Using .Net How to Unblock Your AI PR Review Bottleneck: A Tech Lead’s Guide to Building a Codebase-Aware Reviewer How to Navigate Microservices as a Frontend Engineer How to Compress PDF Files in the Browser Using JavaScript (Step-by-Step) Stanford's youngest instructor talks InfoSec, AI, and catching cheaters - Rachel Fernandez interview [Podcast #217] Product Experimentation with Propensity Scores: Causal Inference for LLM-Based Features in Python How to Build a Multi-Agent AI System with LangGraph, MCP, and A2A [Full Book] How to Land Your First Cloud or DevOps Role: What Hiring Managers Actually Look For How to Deploy a Serverless Spam Classifier Using Scikit-Learn, AWS Lambda, & API Gateway How to Dockerize a Go Application – Full Step-by-Step Walkthrough Learn Hardware, Cloud, DevOps, Networking, Security, Databases, DNS, Git, and Linux Inside TreeHacks 2026, Stanford’s Elite Student Hakc Inside Stanford’s Elite Student Hackathon [Full Documentary] How to Measure Your AI Citation Rate Across ChatGPT, Perplexity, and Claude How to Deploy a Full-Stack Next.js App on Cloudflare Workers with GitHub Actions CI/CD How to Build a Multi-Tenant SaaS Platform with Next.js, Express, and Prisma How I Completed 15 freeCodeCamp Certifications in 4 Months: A Structured Learning Journey How to Build an Agentic Terminal Workflow with GitHub Copilot CLI and MCP Servers How AI Changed the Economics of Writing Clean Code How to Apply STRIDE Threat Modeling and SonarQube Analysis for Secure Software Development How to Set Up OpenID Connect (OIDC) in GitHub Actions for AWS How to Split PDF Files in the Browser Using JavaScript (Step-by-Step) How to Build Your Own Language-Specific LLM [Full Handbook] How to Build a Self-Learning RAG System with Knowledge Reflection How to Trace Multi-Agent AI Swarms with Jaeger v2 How I Tested Malaysia's Open Data Portals with Plain English How I Built a Production-Ready CI/CD Pipeline for a Monorepo-Based Microservices System with Jenkins, Docker Compose, and Traefik The Hidden Tax of Infrastructure: Why Your Team Shouldn’t Be Running It Anymore From Metrics to Meaning: How PaaS Helps Developers Understand Production From Symptoms to Root Cause: How to Use the 5 Whys Technique Product Experimentation for AI Rollouts: Why A/B Testing Breaks and How Difference-in-Differences in Python Fixes It How to Create a GPU-Optimized Machine Image with HashiCorp Packer on GCP 3D Web Development with Blender and Three.js How to Fix a Failing GitHub PR: Debugging CI, Lint Errors, and Build Errors Step by Step How to Merge PDF Files in the Browser Using JavaScript (Step-by-Step) How to Handle Stripe Webhooks Reliably with Background Jobs How to Build an Automatic Knowledge Graph for Your Blog with PHP and JSON-LD Understanding Proxies and Reverse Proxies: Your Gateway to Secure Networking The Evolution of Nvidia Blackwell GPU Memory Architecture How to Use PostgreSQL as a Cache, Queue, and Search Engine The New Definition of Software Engineering in the Age of AI Reclaim Your Time – Master Automation with Zapier How to Create Dynamic Emails in Go with React Email Why Many Beginner Self-Taught Developers Struggle (And What to Do About It) How to Build a Headless WordPress Frontend with Astro SSR on Cloudflare Pages How to Make Your GitHub Profile Stand Out How to Use Context Hub (chub) to Build a Companion Relevance Engine Why Chrome OS Is the Operating System the AI Era Was Built For How to Build Microservices-Based REST APIs for Healthcare Portals How to friction-max your learning with software engineer Jessica Rose [Podcast #216] Shadow AI Explained: Why Employees Are Using AI Behind Your Back Traditional Scraping vs AI Scraping: A Practical Guide for Developers and Data Teams How Database Indexes Work – A Practical Guide with PostgreSQL Examples How to Streamline Search in Web Applications with Elasticsearch How to Build an Open Source Data Lake for Batch Ingestion OpenAI Codex Essentials – AI Assisted Agentic Development Course Learn Software System Design How to Generate PDF Files in the Browser Using JavaScript (With a Real Invoice Example) How to Get Started with Terraform Service-to-Service Communication: When to Use REST, gRPC, and Event-Driven Messaging The Data Quality Handbook: Data Errors, the Developer's Role, and Validation Layers Explained. United States Residential Proxy: Why Local IP Accuracy Matters for SERP, Ads, and Pricing How to Build a Fashion App That Helps You Organize Your Wardrobe How to Build an Admin Dashboard Sidebar with shadcn/ui and Base UI The AI Governance Handbook: How to Build Responsible AI Systems That Actually Ship How to Build a Local DevOps HomeLab with Docker, Kubernetes, and Ansible How to Use Mixins in Flutter [Full Handbook] How to Prep for Technical Interviews – A Guide for Web Developers GPT-5.4 vs GLM-5: Is Open Source Finally Matching Proprietary AI? Data Visualization Tools for Svelte Developers How to Keep Human Experts Visible in Your AI-Assisted Codebase Efficient Data Processing in Python: Batch vs Streaming Pipelines Explained How to Build and Deploy Multi-Architecture Docker Apps on Google Cloud Using ARM Nodes (Without QEMU) How to Build a Secure AI PR Reviewer with Claude, GitHub Actions, and JavaScript How to Build a Positioning-Based Crude Oil Strategy in Python [Full Handbook] How to learn programming and CS in the AI hype era – interview with dev and prof Mark Mahoney [Podcast #215] CUDA Programming for NVIDIA H100s How to Build Reliable AI Systems. How to Build an Online Marketplace with Next.js, Express, and Stripe Connect How to Build a Cost-Efficient AI Agent with Tiered Model Routing The WebCodecs Handbook: Native Video Processing in the Browser The Bluetooth LE Audio Handbook: From "Why Does My Call Sound Like a Tin Can?" to AOSP Implementation How to Set Up OpenClaw and Design an A2A Plugin Bridge
A Developer’s Guide to Lazy Loading in React and Next.js
2026-04-15 · via freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
A Developer’s Guide to Lazy Loading in React and Next.js

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

Lazy loading helps solve this problem by splitting your code into smaller chunks and loading them only when they are needed

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

Table of Contents

What is Lazy Loading?

Lazy loading is a performance technique that defers loading code until it's needed. Instead of loading your entire app at once, you split it into smaller chunks. The browser only downloads a chunk when the user navigates to that route or interacts with that feature.

Benefits include:

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

  • Better Core Web Vitals: Improves Largest Contentful Paint and Total Blocking Time

  • Lower bandwidth: Users only download what they use

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

Prerequisites

Before you follow along, you should have:

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

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

  • A React app (Create React App or Vite) or a Next.js app (for the Next.js examples)

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

How to Use React.lazy for Code Splitting

React.lazy() lets you define a component as a dynamic import. React will load that component only when it's first rendered.

React.lazy() expects a function that returns a dynamic import(). The imported module must use a default export.

Here's a basic example:

import { lazy } from 'react';

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

function App() {
  return (
    <div>
      <h1>My App</h1>
      <HeavyChart />
      <AdminDashboard />
    </div>
  );
}

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

const ComponentWithNamedExport = lazy(() =>
  import('./MyComponent').then((module) => ({
    default: module.NamedComponent,
  }))
);

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

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

React.lazy() alone isn't enough. You must wrap lazy components in Suspense so React knows what to show while they load.

How to Use Suspense with React.lazy

Suspense is a React component that shows a fallback UI while its children are loading. It works with React.lazy() to handle the loading state of dynamically imported components.

Wrap your lazy components in Suspense and provide a fallback prop:

import { lazy, Suspense } from 'react';

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

function App() {
  return (
    <div>
      <h1>My App</h1>
      <Suspense fallback={<div>Loading chart...</div>}>
        <HeavyChart />
      </Suspense>
      <Suspense fallback={<div>Loading dashboard...</div>}>
        <AdminDashboard />
      </Suspense>
    </div>
  );
}

You can use a single Suspense boundary for multiple lazy components:

<Suspense fallback={<div>Loading...</div>}>
  <HeavyChart />
  <AdminDashboard />
</Suspense>

A more polished fallback improves perceived performance:

function LoadingSpinner() {
  return (
    <div className="loading-container">
      <div className="spinner" />
      <p>Loading...</p>
    </div>
  );
}

<Suspense fallback={<LoadingSpinner />}>
  <HeavyChart />
</Suspense>

How to Handle Errors with Error Boundaries

React.lazy() and Suspense don't handle loading errors (for example, network failures or missing chunks). For that, you need an Error Boundary.

Error Boundaries are class components that use componentDidCatch or static getDerivedStateFromError to catch errors in their child tree and render a fallback UI.

Here is a simple Error Boundary:

import { Component } from 'react';

class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    console.error('Error caught by boundary:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback || <div>Something went wrong.</div>;
    }
    return this.props.children;
  }
}

Wrap your Suspense boundary with an Error Boundary:

import { lazy, Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';

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

function App() {
  return (
    <ErrorBoundary fallback={<div>Failed to load chart. Please try again.</div>}>
      <Suspense fallback={<div>Loading chart...</div>}>
        <HeavyChart />
      </Suspense>
    </ErrorBoundary>
  );
}

If the chunk fails to load, the Error Boundary catches it and shows your fallback instead of a blank screen or unhandled error.

How to Use next/dynamic in Next.js

Next.js provides next/dynamic, which wraps React.lazy() and Suspense and adds options tailored for Next.js (including Server-Side Rendering).

Basic usage:

'use client';

import dynamic from 'next/dynamic';

const ComponentA = dynamic(() => import('../components/A'));
const ComponentB = dynamic(() => import('../components/B'));

export default function Page() {
  return (
    <div>
      <ComponentA />
      <ComponentB />
    </div>
  );
}

Custom Loading UI

Use the loading option to show a placeholder while the component loads:

const HeavyChart = dynamic(() => import('../components/HeavyChart'), {
  loading: () => <p>Loading chart...</p>,
});

Disable Server-Side Rendering

For components that must run only on the client (for example, those using window or browser-only APIs), set ssr: false:

const ClientOnlyMap = dynamic(() => import('../components/Map'), {
  ssr: false,
  loading: () => <p>Loading map...</p>,
});

Note: ssr: false works only for Client Components. Use it inside a 'use client' file.

Load on Demand

You can load a component only when a condition is met:

'use client';

import { useState } from 'react';
import dynamic from 'next/dynamic';

const Modal = dynamic(() => import('../components/Modal'), {
  loading: () => <p>Opening modal...</p>,
});

export default function Page() {
  const [showModal, setShowModal] = useState(false);

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Open Modal</button>
      {showModal && <Modal onClose={() => setShowModal(false)} />}
    </div>
  );
}

Named Exports

For named exports, return the component from the dynamic import:

const Hello = dynamic(() =>
  import('../components/hello').then((mod) => mod.Hello)
);

Using Suspense with next/dynamic

In React 18+, you can use suspense: true to rely on a parent Suspense boundary instead of the loading option:

const HeavyChart = dynamic(() => import('../components/HeavyChart'), {
  suspense: true,
});

// In your component:
<Suspense fallback={<div>Loading...</div>}>
  <HeavyChart />
</Suspense>

Important: When using suspense: true, you can't use ssr: false or the loading option. Use the Suspense fallback instead.

React.lazy vs next/dynamic: When to Use Each

Feature React.lazy + Suspense next/dynamic
Framework Any React app (Create React App, Vite, etc.) Next.js only
Server-Side Rendering Not supported Supported by default
Disable SSR N/A ssr: false option
Loading UI Suspense fallback prop Built-in loading option
Error handling Requires Error Boundary Requires Error Boundary
Named exports Manual .then() mapping Same .then() pattern
Suspense mode Always uses Suspense Optional via suspense: true

When to Use React.lazy

  • You're building a pure React app (no Next.js)

  • You use Create React App, Vite, or a custom Webpack setup

  • You don't need Server-Side Rendering

  • You want a simple, framework-agnostic approach

When to Use next/dynamic

  • You're building a Next.js app

  • You need SSR for some components and want to disable it for others

  • You want built-in loading placeholders without manually adding Suspense

  • You want Next.js-specific optimizations and defaults

Real-World Examples

Example 1: Route-Based Code Splitting in React

Split your app by route so each page loads only when the user navigates to it:

// App.jsx
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import ErrorBoundary from './ErrorBoundary';

const Home = lazy(() => import('./pages/Home'));
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Settings = lazy(() => import('./pages/Settings'));

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

Example 2: Lazy Loading a Heavy Chart Library in Next.js

Defer loading a chart library until the user opens the analytics section:

// app/analytics/page.jsx
'use client';

import { useState } from 'react';
import dynamic from 'next/dynamic';

const Chart = dynamic(() => import('../components/Chart'), {
  ssr: false,
  loading: () => (
    <div className="chart-skeleton">
      <div className="skeleton-bar" />
      <div className="skeleton-bar" />
      <div className="skeleton-bar" />
    </div>
  ),
});

export default function AnalyticsPage() {
  const [showChart, setShowChart] = useState(false);

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

Example 3: Lazy Loading a Modal

Load a modal component only when the user clicks to open it:

// React (with React.lazy)
import { lazy, Suspense, useState } from 'react';

const Modal = lazy(() => import('./Modal'));

function ProductPage() {
  const [showModal, setShowModal] = useState(false);

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Add to Cart</button>
      {showModal && (
        <Suspense fallback={null}>
          <Modal onClose={() => setShowModal(false)} />
        </Suspense>
      )}
    </div>
  );
}
// Next.js (with next/dynamic)
'use client';

import { useState } from 'react';
import dynamic from 'next/dynamic';

const Modal = dynamic(() => import('./Modal'), {
  loading: () => null,
});

export default function ProductPage() {
  const [showModal, setShowModal] = useState(false);

  return (
    <div>
      <button onClick={() => setShowModal(true)}>Add to Cart</button>
      {showModal && <Modal onClose={() => setShowModal(false)} />}
    </div>
  );
}

Example 4: Lazy Loading External Libraries

Load a library only when the user needs it (for example, when they start typing in a search box):

'use client';

import { useState } from 'react';

const names = ['Alice', 'Bob', 'Charlie', 'Diana'];

export default function SearchPage() {
  const [results, setResults] = useState([]);
  const [query, setQuery] = useState('');

  const handleSearch = async (value) => {
    setQuery(value);
    if (!value) {
      setResults([]);
      return;
    }
    // Load fuse.js only when user searches
    const Fuse = (await import('fuse.js')).default;
    const fuse = new Fuse(names);
    setResults(fuse.search(value));
  };

  return (
    <div>
      <input
        type="text"
        placeholder="Search..."
        value={query}
        onChange={(e) => handleSearch(e.target.value)}
      />
      <ul>
        {results.map((result) => (
          <li key={result.refIndex}>{result.item}</li>
        ))}
      </ul>
    </div>
  );
}

Conclusion

Lazy loading improves performance by splitting your bundle and loading code only when needed. Here's what you learned:

  • React.lazy() – Use in plain React apps for code splitting. It requires a default export and works with dynamic import().

  • Suspense – Wrap lazy components in Suspense and provide a fallback for the loading state.

  • Error Boundaries – Use them to catch chunk load failures and show a friendly error UI.

  • next/dynamic – Use in Next.js for the same benefits plus SSR control and built-in loading options.

Choose React.lazy for React-only projects and next/dynamic for Next.js. Combine them with Suspense and Error Boundaries for a solid lazy-loading setup.

Start by identifying your heaviest components (charts, modals, admin panels) and lazy load them. Measure your bundle size and Core Web Vitals before and after to see the impact.



Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started