perf hacks
BundlesAnalysis

Shrinking Your Bundle

Find what's bloating your JavaScript and fix it in 30 minutes.

BUNDLE SPLITTINGbundle.js500KBmainvendorutilschartlazymodal150KBinitial load+ lazy chunkson demand

Hidden Cost

A bloated bundle costs you twice: slow page loads AND higher bandwidth bills. Every extra KB is paid for on every page load.

Setup

Install the analyzer

npm install @next/bundle-analyzer

Configure Next.js

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

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

Run the analysis

ANALYZE=true npm run build

Opens an interactive treemap. Bigger rectangles = bigger problems.

The Usual Suspects

LibrarySizeReplace With
moment300KBdate-fns (20KB)
lodash (full)70KBDirect imports
Icon libraries100KB+Direct imports or @iconify/react
@aws-sdk/*500KB+Should be server-only
chart.js200KBLazy load it

Quick Fixes

Moment → date-fns

// Before
import moment from 'moment';
moment(date).format('YYYY-MM-DD');

// After
import { format } from 'date-fns';
format(date, 'yyyy-MM-dd');

Lodash Direct Imports

// Before: pulls in everything
import _ from 'lodash';
_.debounce(fn, 300);

// After: just what you need
import debounce from 'lodash/debounce';
debounce(fn, 300);

Icon Library Fixes

// Before: may import all icons
import { FaHome } from 'react-icons/fa';

// After: specific import path
import { FaHome } from 'react-icons/fa6';

Auto-Fix with modularizeImports

Force proper tree-shaking for problem packages:

next.config.js
module.exports = {
  modularizeImports: {
    'lodash': {
      transform: 'lodash/{{member}}',
    },
    '@mui/icons-material': {
      transform: '@mui/icons-material/{{member}}',
    },
    '@heroicons/react/24/outline': {
      transform: '@heroicons/react/24/outline/{{member}}',
    },
  },
};

Now import { debounce } from 'lodash' automatically becomes import debounce from 'lodash/debounce'.

The Barrel File Problem

Hidden Bundle Bloat

Barrel files (index.ts re-exports) are a common source of unexpectedly large bundles.

// components/index.ts - this is a barrel file
export * from './Button';
export * from './Modal';
export * from './Chart'; // 200KB!
// Importing one thing evaluates everything
import { Button } from '@/components'; // Pulls in Chart too

Import from source files directly:

import { Button } from '@/components/Button';

Verification Checklist

Check for oversized packages No single package should exceed 100KB without justification. Target under 200KB total JS for initial load.

Verify tree shaking Ensure no server-only packages appear in the client bundle. Icon libraries should be properly tree-shaken.

Eliminate barrel file imports Import directly from source files, not from index.ts re-exports for large modules.

Check for duplicates Look for the same package appearing in multiple chunks with different versions.

Verify dynamic imports Heavy components should be dynamically imported. Third-party scripts should be deferred or lazy loaded.


Next: Dynamic Imports — load heavy code only when needed.

For advanced forensics: DevTools Debugging — Chrome memory dumps, chunk inspection, and LLM-powered bundle analysis.

On this page