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.
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.
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.
You've completed the performance section. Next, move into deployment — starting with a general overview before covering Vercel, environment variables, and Docker.