Skip to main content

webpack-bundle-analyzer Guide

webpack-bundle-analyzer generates an interactive treemap of your JavaScript bundle, showing exactly what's inside each chunk. Use it to find bloated dependencies, duplicate packages, and dead code costing your users download time.

✓ Installation & setup ✓ Reading the treemap ✓ Bundle reduction techniques ✓ CI integration

Installation & Basic Setup

npm install --save-dev webpack-bundle-analyzer
// webpack.config.js
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

module.exports = {
  // ... other config
  plugins: [
    // Opens browser with interactive treemap
    new BundleAnalyzerPlugin({
      analyzerMode: 'server',       // 'server' | 'static' | 'json' | 'disabled'
      analyzerPort: 8888,
      openAnalyzer: true,
      generateStatsFile: true,      // also write stats.json
      statsFilename: 'stats.json',
    }),
  ],
};

npm Script Integration

// package.json — only run analyzer when needed
{
  "scripts": {
    "build": "webpack --mode production",
    "build:analyze": "ANALYZE=true webpack --mode production",
    "analyze": "webpack-bundle-analyzer dist/stats.json"
  }
}

// webpack.config.js — conditional plugin
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');

const plugins = [];
if (process.env.ANALYZE) {
  plugins.push(new BundleAnalyzerPlugin());
}

Size Metrics Explained

Size Type What It Measures Optimize For?
Stat sizeRaw input file size before webpack processingNo
Parsed sizeAfter minification and dead code eliminationSecondary
Gzip sizeCompressed size — what users actually downloadPrimary

Common Bundle Bloat & Fixes

Bloat Source Before Fix After
moment.js66KB gzipSwitch to day.js2KB gzip
Full lodash24KB gziplodash-es + tree shake1–3KB gzip
All locales50KB+ gzipContextReplacementPlugin2KB gzip
Unsplit routes500KB+ mainDynamic import()50KB main

Code Splitting with Dynamic Imports

// Before: static import bundles everything together
import AdminDashboard from './AdminDashboard';

// After: dynamic import creates separate chunk
const AdminDashboard = React.lazy(() => import('./AdminDashboard'));

// Route-level splitting with React Router
const routes = [
  {
    path: '/dashboard',
    component: React.lazy(() => import('./pages/Dashboard')),
  },
  {
    path: '/admin',
    component: React.lazy(
      () => import(/* webpackChunkName: "admin" */ './pages/Admin')
    ),
  },
];

// webpack.config.js: vendor chunk splitting
optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        priority: 10,
      },
      react: {
        test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
        name: 'react',
        priority: 20,
      },
    },
  },
}

Frequently Asked Questions

How do I install and run webpack-bundle-analyzer?▼

Install as a dev dependency: `npm install --save-dev webpack-bundle-analyzer`. Then add it to your webpack config plugins array: `new BundleAnalyzerPlugin()`. Run your build with `npm run build` and the analyzer opens a browser with a treemap visualization. For a JSON report without opening a browser, set `analyzerMode: 'json'` and `reportFilename: 'stats.json'`.

What is the difference between stat size, parsed size, and gzip size?▼

Stat size is the raw file size before any webpack transformations (minification, tree-shaking). Parsed size is the size after webpack processes the file (minified, dead code removed). Gzip size is the parsed size after gzip compression — this is what users actually download. Always optimize for gzip size since that's the real network cost. Brotli typically gives 10–15% better compression than gzip for text assets.

What should I look for in the bundle analyzer treemap?▼

Look for: (1) Large node_modules taking disproportionate space — candidates for code-splitting or replacement with lighter alternatives. (2) Duplicate packages — multiple versions of lodash, React, etc. (3) Dev-only code included in production (test utilities, mock data). (4) Full libraries when only a few functions are used (e.g., importing all of lodash instead of lodash/pick). (5) Locale/i18n files for all languages when only one is needed (moment.js locale bloat).

How do I reduce my webpack bundle size?▼

Key techniques: (1) Code splitting — use dynamic `import()` for routes/features. (2) Tree shaking — use ES modules and set `sideEffects: false` in package.json. (3) Replace heavy libraries — swap moment.js for day.js (66KB vs 2KB), lodash for lodash-es with tree shaking. (4) Lazy-load non-critical components. (5) Configure `optimization.splitChunks` to extract vendor chunks. (6) Use `webpackPrefetch: true` for routes likely to be visited.

Share this tool: X / Twitter LinkedIn
✓ 60,000+ developers use DevPlaybook ★★★★★ 4.8 / 5 on Gumroad ✓ MIT licensed · Instant download ✓ No login required

Related Products

on Gumroad

You Might Also Need

More Free Tools

Enjoying this tool? Get more like it.

Weekly developer tool guides, productivity playbooks & AI tricks. Free. No spam.

DevPlaybook Pro 7 days free

Unlock AI-Powered Dev Tools

  • ⚡ AI Code Review, Doc Generator & SQL Builder
  • ⚡ All premium templates & early access
  • ⚡ Member discounts on Gumroad products
Start Free Trial →

$9/mo after trial · Cancel anytime

Want the full toolkit?

Get DevPlaybook Pro

Every template, guide, boilerplate, and automation script in one bundle. 13 premium products — grab them all at once and save big.

$79
$241 separately Save $162 (67% off)
Get DevPlaybook Pro — $79 →

MIT licensed · Instant download · No subscription

See what's included → Browse all deals →