“Trust in the Lord with all your heart and lean not on your own understanding; in all your ways submit to him, and he will make your paths straight.” – Proverbs 3:5-6

Code Splitting vs Lazy Loading in React and Next.js — A Beginner-Friendly Deep Dive

14 min read
20 views
Cover Image

This blog explains the difference between code splitting and lazy loading in React and Next.js. It walks beginners through how these two techniques work together to improve app performance, reduce bundle size, and optimize user experience. With clear examples and real-world use cases, readers will understand when and how to apply lazy loading effectively — especially in Next.js App Router projects.

Have you ever noticed how some websites load instantly while others take forever — even though they look similar?

That’s often the difference between loading everything at once and loading only what’s needed.

Two powerful techniques make this possible in React and Next.js: 👉 Code Splitting and Lazy Loading.

They sound similar, but they’re not the same. In this guide, we’ll explore both — what they mean, why they matter, and how to use them to build faster, smoother apps.


🚀 Why You Should Care About These Techniques

When a web app loads, the browser has to:

  1. Download all the JavaScript.
  2. Parse and execute it before showing the page.

If your app is small, that’s fine. But once you add charts, maps, rich editors, or analytics tools, your JavaScript bundle gets huge — slowing everything down.

That’s where code splitting and lazy loading come to the rescue:

  • They break big code into smaller chunks, and
  • Load those chunks only when needed.

Result? ✅ Faster page loads ✅ Lower memory use ✅ Happier users (and search engines)


🧩 What Is Code Splitting?

Code Splitting means dividing your JavaScript bundle into smaller pieces (chunks) instead of shipping one giant file to the browser.

It’s like splitting a thick textbook into separate chapters — the browser only loads the chapter (page) the user opens.

Example: How Next.js Does Code Splitting Automatically

In Next.js, each page inside the /app or /pages folder becomes its own bundle automatically:

jsx
// app/page.tsx
export default function Home() {
  return <h1>Home</h1>;
}

// app/dashboard/page.tsx
export default function Dashboard() {
  return <h1>Dashboard</h1>;
}

When you visit /, Next.js only sends the Home page code. When you go to /dashboard, it loads that page’s bundle separately.

💡 Why It Matters

  • Faster initial load time
  • Better Core Web Vitals
  • Reduced data usage on slow networks

🧠 Think of code splitting as something that happens at build time — it’s your app’s structure being divided into smaller files before deployment.


💤 What Is Lazy Loading?

Lazy Loading controls when those code chunks are fetched.

Instead of loading everything immediately, the browser waits until a part of your app is actually needed — then it downloads that part on demand.

For example, a chart on your dashboard might not need to load until the user scrolls down to see it.

Example: Lazy Loading in React

jsx
import React, { Suspense } from "react";

const Chart = React.lazy(() => import("./Chart"));

function Dashboard() {
  return (
    <Suspense fallback={<p>Loading chart...</p>}>
      <Chart />
    </Suspense>
  );
}

Here’s what happens:

  • React splits the Chart component into its own chunk.
  • That chunk is only loaded when <Chart /> is rendered.
  • The fallback (Loading chart...) shows temporarily while it loads.

So, lazy loading happens at runtime — when the app is already running in the browser.


⚙️ Lazy Loading in Next.js (App Router Style)

Next.js gives you an easy way to lazy load components using the next/dynamic function:

jsx
import dynamic from "next/dynamic";

const Chart = dynamic(() => import("../components/Chart"), {
  loading: () => <p>Loading chart...</p>,
  ssr: false,
});

export default function Dashboard() {
  return (
    <>
      <Sidebar />
      <Chart />
    </>
  );
}

Explanation:

  • dynamic() turns your Chart into a lazy-loaded component.
  • ssr: false tells Next.js not to server-render it — useful for components that rely on browser APIs (like Chart.js or Maps).
  • The loading option defines a simple placeholder or skeleton while the component loads.

💡 In Next.js 14+, pages in the App Router are Server Components by default, meaning only client-side interactivity (like charts or maps) should be lazy-loaded.


🧠 Code Splitting vs Lazy Loading — The Difference

FeatureCode SplittingLazy Loading
What it doesDivides code into smaller chunksLoads those chunks on demand
When it happensAt build timeAt runtime
Who controls itNext.js / Webpack automaticallyYou decide when to load
GoalReduce bundle sizeImprove perceived speed
ExampleEach route gets its own JS bundleChart loads only when rendered

👉 Code splitting creates smaller bundles. 👉 Lazy loading decides when to load them.

Together, they make your app faster and lighter.


⚡️ Real-World Use Cases

Lazy loading is best when a component is heavy, optional, or not immediately visible.

✅ Use Lazy Loading For:

  • Charts (Chart.js, Recharts)
  • Maps (Google Maps, Leaflet)
  • Text editors (React Quill, Monaco)
  • Modals or popups
  • Image galleries or carousels below the fold

🚫 Avoid Lazy Loading For:

  • Navbar
  • Hero section
  • Main content
  • SEO-critical or above-the-fold UI

If you lazy-load your main UI, users will just stare at a blank screen longer.


🧩 Summary Rule of Thumb

SituationLazy Load?Why
Navbar, Hero, Main ContentNeeded immediately
Charts, Maps, Code EditorsHeavy and secondary
Modal opened laterOnly needed on user action
Common Buttons, LayoutToo small; reused everywhere
Image gallery below the foldImproves initial load speed

⚖️ A Balanced Example — Dashboard Page

Here’s a smart way to structure your dashboard in Next.js 14+:

app/dashboard/page.tsx

jsx
import Sidebar from "@/components/Sidebar";
import Chart from "@/components/Chart.lazy";
import Editor from "@/components/Editor.lazy";

export default function DashboardPage() {
  return (
    <>
      <Sidebar />
      <Chart />
      <Editor />
    </>
  );
}

components/Chart.lazy.tsx

jsx
"use client";
import dynamic from "next/dynamic";

const Chart = dynamic(() => import("./Chart"), {
  loading: () => <p>Loading chart...</p>,
  ssr: false,
});

export default Chart;

✅ Server Component (page) stays light and SEO-friendly. ✅ Chart and Editor load only on the client. ✅ Clean separation and faster overall experience.


🧮 Measuring the Impact

1. Analyze Bundle Size with @next/bundle-analyzer

Install:

bash
npm install @next/bundle-analyzer

In next.config.js:

js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
});

module.exports = withBundleAnalyzer({});

Then run:

bash
ANALYZE=true npm run build

You’ll see a visual report showing which bundles are large. After lazy loading, those heavy components (like Chart.js) move into separate async chunks.


2. Test Performance with Lighthouse

Run a Lighthouse test (Chrome DevTools → “Lighthouse” tab).

You’ll likely see major improvements:

MetricBeforeAfter Lazy Loading
First Contentful Paint (FCP)~2.5s~1.2s
Largest Contentful Paint (LCP)~3.0s~1.6s
Total Blocking Time (TBT)~500ms~150ms

That’s a noticeable boost in real-world performance.


🧭 Best Practices

RuleRecommendation
Split routes automaticallyLet Next.js handle page-level code splitting
Lazy-load heavy UICharts, Maps, Editors, Modals
Keep critical UI eagerNavbar, Hero, Core Content
Use friendly fallbacksSkeletons or loading placeholders
Check bundle sizeUse @next/bundle-analyzer
Measure resultsLighthouse, WebPageTest, or Chrome DevTools

✨ Final Thoughts

Code Splitting and Lazy Loading are like teammates:

  • One cuts your code into pieces,
  • The other decides when to load each piece.

In Next.js (especially versions 14 and 15), both are built-in and incredibly easy to use.

Use them wisely — lazy load what’s secondary, and render what’s essential. Your users (and Google’s performance metrics) will thank you for it.

S

Written by Shankalpa Pokharel

Created on

Share this post

More Articles

Discover other posts you might enjoy