← Back to Performance

Bundle size management and optimization with performance budgets

BUDGETSPerformance Budget Targets

Recommended bundle size limits by connection and device type

📱 Mobile Budgets (3G)

170KB
Critical Resources

Initial HTML + CSS + JS

130KB
JavaScript Bundle

Main + vendor chunks

40KB
CSS Bundle

Critical + deferred

Based on 5s load time on 3G connection (1.6Mbps)

💻 Desktop Budgets (Fast 3G+)

500KB
Critical Resources

Initial load budget

350KB
JavaScript Bundle

Main application code

150KB
CSS Bundle

Styles + frameworks

Optimized for sub-3s load time on fast connections

WEBPACKBundle Analysis Tools

Tools and techniques to analyze and optimize bundle sizes

🔍 Analysis Tools

// Webpack Bundle Analyzer
npm install --save-dev webpack-bundle-analyzer

// package.json script
"analyze": "npm run build && npx webpack-bundle-analyzer build/static/js/*.js"

// Next.js bundle analysis
npm install --save-dev @next/bundle-analyzer

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

module.exports = withBundleAnalyzer({
  // Next.js config
})

// Run analysis
ANALYZE=true npm run build

// Source Map Explorer
npm install --save-dev source-map-explorer
npx source-map-explorer build/static/js/*.js

📊 Size Tracking

// bundlesize package
npm install --save-dev bundlesize

// package.json
{
  "bundlesize": [
    {
      "path": "./build/static/js/main.*.js",
      "maxSize": "130kb"
    },
    {
      "path": "./build/static/css/*.css",
      "maxSize": "40kb"
    }
  ],
  "scripts": {
    "bundlesize": "bundlesize"
  }
}

// CI Integration
npm run build && npm run bundlesize

// Bundlemon for tracking over time
npm install --save-dev bundlemon
npx bundlemon --subProject "main-app"
SPLITCode Splitting Strategies

Effective patterns for breaking large bundles into manageable chunks

// Route-based splitting (Next.js automatic)
// pages/dashboard.js → dashboard.chunk.js
// pages/profile.js → profile.chunk.js

// Component-based splitting
const HeavyChart = lazy(() => import('./HeavyChart'))
const AdminPanel = lazy(() => import('./AdminPanel'))

// Vendor splitting (Webpack)
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
        common: {
          minChunks: 2,
          chunks: 'all',
          name: 'common'
        }
      }
    }
  }
}

// Feature-based splitting
const FeatureA = lazy(() => import('./features/FeatureA'))
const FeatureB = lazy(() => import('./features/FeatureB'))

// Library splitting for better caching
const ReactChunk = lazy(() => import('./chunks/ReactChunk'))
const UtilsChunk = lazy(() => import('./chunks/UtilsChunk'))
TREETree Shaking Optimization

Eliminating dead code to reduce bundle size

🌳 ES6 Module Imports

// ❌ Imports entire library
import _ from 'lodash'
import * as utils from './utils'

// ✅ Import only what you need
import { debounce, throttle } from 'lodash'
import { formatDate } from './utils'

// ✅ Library-specific optimized imports
import debounce from 'lodash/debounce'
import Button from '@mui/material/Button'

// ✅ Conditional imports
const HeavyModule = await import('./HeavyModule')
if (condition) {
  const { helper } = await import('./helpers')
}

// babel-plugin-import for automatic optimization
{
  "plugins": [
    ["import", {
      "libraryName": "antd",
      "libraryDirectory": "es",
      "style": "css"
    }]
  ]
}

🗑️ Dead Code Elimination

// Webpack production config
module.exports = {
  mode: 'production', // Enables tree shaking
  optimization: {
    usedExports: true,
    sideEffects: false, // Safe if no side effects
    minimize: true
  }
}

// package.json sideEffects declaration
{
  "sideEffects": [
    "*.css",
    "*.scss",
    "./src/polyfills.js"
  ]
}

// ESLint dead code detection
"rules": {
  "no-unused-vars": "error",
  "no-unreachable": "error"
}

// Remove console.logs in production
const TerserPlugin = require('terser-webpack-plugin')

optimization: {
  minimizer: [
    new TerserPlugin({
      terserOptions: {
        compress: {
          drop_console: true,
          drop_debugger: true
        }
      }
    })
  ]
}
MODERNModern Browser Bundles

Serving optimized bundles to modern browsers

// Next.js modern bundle (automatic)
// Generates both modern and legacy bundles

// Vite modern build
export default {
  build: {
    target: ['es2015', 'chrome58', 'firefox57', 'safari11'],
    modernPolyfills: true
  }
}

// Manual differential serving
<script type="module" src="modern-bundle.js"></script>
<script nomodule src="legacy-bundle.js"></script>

// Babel preset-env for modern browsers
{
  "presets": [
    ["@babel/preset-env", {
      "targets": {
        "esmodules": true
      },
      "bugfixes": true,
      "shippedProposals": true
    }]
  ]
}

// Webpack 5 automatic target detection
module.exports = {
  target: ['web', 'es2017'],
  experiments: {
    outputModule: true
  }
}

// Size comparison
Legacy bundle: 450KB
Modern bundle: 320KB (-29%)
Savings: No polyfills, native syntax
MONITORBundle Size Monitoring

Continuous monitoring and alerting for bundle size regression

🔧 CI/CD Integration

# GitHub Actions
name: Bundle Size Check
on: [pull_request]

jobs:
  bundle-size:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
      - run: npm ci
      - run: npm run build
      - uses: andresz1/size-limit-action@v1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

# size-limit config
module.exports = [
  {
    path: 'build/static/js/*.js',
    limit: '130 KB'
  },
  {
    path: 'build/static/css/*.css',
    limit: '40 KB'
  }
]

📈 Performance Tracking

Bundle Size Trends
Week 1
125KB
Week 2
132KB
Week 3
145KB ⚠️
OPTIMIZEBundle Optimization Techniques

Advanced techniques to minimize bundle sizes

✅ OPTIMIZATIONS

  • • Use dynamic imports for heavy features
  • • Implement route-based code splitting
  • • Remove unused dependencies regularly
  • • Choose lighter alternative libraries
  • • Enable gzip/brotli compression
  • • Optimize images and assets
  • • Use CDN for common libraries
  • • Implement service worker caching

❌ AVOID

  • • Including entire libraries for small features
  • • Ignoring bundle analysis reports
  • • Over-splitting into too many chunks
  • • Including dev dependencies in production
  • • Forgetting to remove dead code
  • • Not monitoring bundle size changes
  • • Using heavy polyfills unnecessarily
  • • Duplicate dependencies across chunks