Bitlyst

When Should You Use Dynamic Import in React/Next.js? (With Performance Comparison)

Dynamic import lets you lazy load components so they’re only loaded when needed, instead of bundling everything up front.


1) What is Dynamic Import?

// Static import (always in initial bundle)
import BigChart from "./BigChart"

// Dynamic import (code-split, loaded on demand)
import dynamic from "next/dynamic"
const BigChart = dynamic(() => import("./BigChart"))

2) Why Use It?

Faster initial load (smaller JS)
Conditional loading (only when needed)
Avoid SSR issues for client-only libs ({ ssr: false })


3) Good Use Cases


4) Real-World Examples

a) Rich text editor (react-quill)

import dynamic from "next/dynamic"
const RichTextEditor = dynamic(() => import("react-quill"), { ssr: false })

export default function Page() {
  return (
    <div>
      <h1>Create Post</h1>
      <RichTextEditor theme="snow" />
    </div>
  )
}

b) Charts (react-chartjs-2)

import dynamic from "next/dynamic"
const Chart = dynamic(() => import("react-chartjs-2"), { ssr: false })

export default function Dashboard() {
  return (
    <section>
      <h2>Analytics</h2>
      <Chart type="bar" data={{ labels: ["A","B","C"], datasets: [{ data: [12,19,3] }] }} />
    </section>
  )
}

5) Performance Comparison (Before vs After)

Below is a sample comparison showing how dynamic import can change bundle breakdown.
Use the measurement steps in the next section to produce your actual numbers.

Chunk/MetricBefore (static import)After (dynamic import)
Initial JS (first load)420 KB240 KB
react-quill in initial bundle170 KB0 KB (lazy)
react-chartjs-2 in initial95 KB0 KB (lazy)
Route JS (dashboard page)210 KB80 KB
Number of JS chunks913
Largest Contentful Paint (LCP)*2.4s1.8s

* LCP depends on network/device; treat this as illustrative. Your actual metrics may vary.


6) How to Measure It in Your App

Option A — @next/bundle-analyzer

  1. Install
npm i -D @next/bundle-analyzer
  1. Configure next.config.js
// next.config.js
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer({
  // your Next.js config
})
  1. Build & Analyze
ANALYZE=true next build
# Then open the generated treemaps (usually in .next/analyze) to inspect chunks.

Option B — Inspect build output

next build
# Check "First Load JS shared by all" and per-route sizes in terminal output.

Option C — Web Vitals in production


7) When NOT to Use It


8) Cheatsheet (TL;DR)

SituationUse Dynamic Import?
Heavy/optional components✔️ Yes
Client-only libraries (need window)✔️ Yes
Feature flags / A/B features✔️ Yes
Always-used layout (navbar/footer)❌ No
Small common components❌ No

Pro tip: Pair dynamic imports with skeletons or loading placeholders so the UI feels responsive while chunks load.

How did you like this post?

👍0
❤️0
🔥0
🤔0
😮0
When Should You Use Dynamic Import in React/Next.js? (With Performance Comparison) · Bitlyst