Skip to content

Bundle Analysis

You can't reliably improve what you don't measure. This lesson covers @next/bundle-analyzer, the official tool for visualizing exactly what's inside your Next.js app's client-side JavaScript bundles.

Visualizing What's Actually in Your Bundle

@next/bundle-analyzer wraps your Next.js build process to generate an interactive treemap visualization showing exactly which packages and modules contribute to your client-side JavaScript, and how large each one is relative to the whole — making it immediately obvious when one unexpectedly large dependency is bloating your bundle.

This is especially useful in Next.js because Server Components already remove a lot of code from the client bundle by default — bundle analysis helps you find what's left, and whether it's actually justified.

// npm install --save-dev @next/bundle-analyzer

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

module.exports = withBundleAnalyzer({
  // your existing config
});

// package.json script
// "analyze": "ANALYZE=true next build"

Running npm run analyze now opens an interactive treemap in your browser after the build completes.

Running an Analysis

ANALYZE=true npm run build

# Opens interactive treemap views for:
# - client bundles
# - server bundles
# - edge runtime bundles (if applicable)
  • The generated report shows separate treemaps for client, server, and edge bundles.
  • Larger boxes in the treemap represent larger contributions to bundle size.
  • Look specifically for large, unexpected dependencies pulled in by a single component.
  • Re-run the analysis after making changes to confirm the actual size impact.

Bundle Analysis Cheat Sheet

Common findings and their typical fixes.

Finding Typical Fix
A large date/utility library used for one small function Replace with a smaller alternative or native APIs
A component library imported entirely for one component Import only the specific component used
A large chart/editor library loaded on every page Dynamically import it only where actually used
Unexpectedly large client bundle overall Check for unnecessary "use client" directives

Reducing Size with Dynamic Imports

Large, rarely-used components (a rich text editor, a complex charting library) don't need to be part of the initial bundle if they're only needed after some user interaction. next/dynamic lets you load such a component's code only when it's actually rendered.

import dynamic from "next/dynamic";

const RichTextEditor = dynamic(() => import("./RichTextEditor"), {
  loading: () => <p>Loading editor...</p>,
});

RichTextEditor's code is now split into its own chunk, downloaded only when it's actually rendered.

Import Only What You Need

Some libraries support "tree shaking" (removing unused code) better than others, depending on how you import from them. Importing a specific function directly, rather than an entire library's default export, often produces a meaningfully smaller bundle.

  • Prefer import { debounce } from "lodash-es" over import _ from "lodash".
  • Check whether a library documents specific "tree-shakeable" import paths.
  • Bundle analysis will confirm whether a specific import change actually reduced size.

Common Mistakes

  • Never running a bundle analysis and guessing at what's making the client bundle large.
  • Importing an entire library when only one small function from it is actually used.
  • Loading large, interaction-gated components (editors, modals with heavy dependencies) eagerly instead of dynamically.
  • Assuming Server Components alone solve all bundle size concerns, without checking the client bundle directly.

Key Takeaways

  • @next/bundle-analyzer visualizes exactly what contributes to your client-side JavaScript bundle.
  • Large, interaction-gated components are good candidates for next/dynamic code splitting.
  • Import specific functions rather than whole libraries where tree-shaking support allows it.
  • Re-run analysis after changes to confirm actual bundle size impact, rather than assuming.
  • Server Components reduce bundle size significantly, but bundle analysis still catches what remains.

Pro Tip

Add bundle analysis as a regular (even if manual) step in your release process for performance-sensitive projects — bundle size tends to creep up gradually as dependencies are added, and catching a large regression early is much easier than untangling it after months of accumulation.