`n

Bundle Size Optimization - Complete Guide

Published: September 25, 2024 | Reading time: 22 minutes

Bundle Optimization Overview

Bundle size optimization improves application performance and loading speed:

Optimization Benefits
# Bundle Optimization Benefits
- Faster loading times
- Reduced bandwidth usage
- Better user experience
- Improved performance
- Lower hosting costs
- Better SEO rankings
- Mobile optimization

Bundle Analysis

Analyzing Bundle Size

Bundle Analysis Tools
# Bundle Analysis Tools

# 1. Webpack Bundle Analyzer
npm install --save-dev webpack-bundle-analyzer

# webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({
      analyzerMode: 'server',
      openAnalyzer: true,
    })
  ]
};

# 2. Webpack Bundle Analyzer CLI
npx webpack-bundle-analyzer dist/main.js

# 3. Source Map Explorer
npm install --save-dev source-map-explorer
npx source-map-explorer 'dist/*.js'

# 4. Bundle Analyzer Script
# package.json
{
  "scripts": {
    "analyze": "webpack-bundle-analyzer dist/main.js",
    "analyze:source": "source-map-explorer 'dist/*.js'"
  }
}

# 5. Webpack Stats
# webpack.config.js
module.exports = {
  stats: {
    chunks: true,
    chunkModules: true,
    modules: true,
    reasons: true,
    usedExports: true,
    providedExports: true,
    optimizationBailout: true,
    errorDetails: true,
    colors: true,
    hash: true,
    timings: true,
    assets: true,
    cached: true,
    cachedAssets: true,
    children: true,
    chunksSort: 'size',
    modulesSort: 'size',
    assetsSort: 'size'
  }
};

# 6. Bundle Size Monitoring
# bundle-size.js
const fs = require('fs');
const path = require('path');

const bundlePath = path.join(__dirname, 'dist', 'main.js');
const stats = fs.statSync(bundlePath);
const sizeInKB = Math.round(stats.size / 1024);

console.log(`Bundle size: ${sizeInKB} KB`);

# 7. CI/CD Bundle Size Check
# .github/workflows/bundle-size.yml
name: Bundle Size Check
on: [push, pull_request]
jobs:
  bundle-size:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: '18'
    - run: npm ci
    - run: npm run build
    - run: npm run analyze

# 8. Bundle Size Budget
# webpack.config.js
module.exports = {
  performance: {
    hints: 'warning',
    maxEntrypointSize: 512000,
    maxAssetSize: 512000,
    assetFilter: function(assetFilename) {
      return assetFilename.endsWith('.js');
    }
  }
};

# 9. Bundle Size Comparison
# compare-bundles.js
const fs = require('fs');
const path = require('path');

function getBundleSize(filePath) {
  const stats = fs.statSync(filePath);
  return Math.round(stats.size / 1024);
}

const currentSize = getBundleSize('dist/main.js');
const previousSize = getBundleSize('dist-previous/main.js');
const difference = currentSize - previousSize;

console.log(`Current: ${currentSize} KB`);
console.log(`Previous: ${previousSize} KB`);
console.log(`Difference: ${difference} KB`);

# 10. Bundle Size Report
# bundle-report.js
const fs = require('fs');
const path = require('path');

function generateReport() {
  const bundlePath = path.join(__dirname, 'dist', 'main.js');
  const stats = fs.statSync(bundlePath);
  const sizeInKB = Math.round(stats.size / 1024);
  
  const report = {
    timestamp: new Date().toISOString(),
    bundleSize: sizeInKB,
    threshold: 500
  };
  
  fs.writeFileSync('bundle-report.json', JSON.stringify(report, null, 2));
}

generateReport();

Webpack Optimization

Webpack Configuration

Webpack Optimization
# Webpack Optimization

# 1. Production Mode
# webpack.config.js
module.exports = {
  mode: 'production',
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,
            drop_debugger: true,
          },
        },
      }),
    ],
  },
};

# 2. Code Splitting
# webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
        common: {
          name: 'common',
          minChunks: 2,
          chunks: 'all',
          enforce: true,
        },
      },
    },
  },
};

# 3. Tree Shaking
# webpack.config.js
module.exports = {
  optimization: {
    usedExports: true,
    sideEffects: false,
  },
};

# 4. Module Concatenation
# webpack.config.js
module.exports = {
  optimization: {
    concatenateModules: true,
  },
};

# 5. Minification
# webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,
            drop_debugger: true,
            pure_funcs: ['console.log'],
          },
          mangle: {
            safari10: true,
          },
        },
      }),
    ],
  },
};

# 6. CSS Optimization
# webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
    }),
  ],
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
};

# 7. Asset Optimization
# webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[contenthash].[ext]',
            },
          },
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: {
                progressive: true,
                quality: 65,
              },
              optipng: {
                enabled: false,
              },
              pngquant: {
                quality: [0.65, 0.90],
                speed: 4,
              },
              gifsicle: {
                interlaced: false,
              },
            },
          },
        ],
      },
    ],
  },
};

# 8. Dynamic Imports
# webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        async: {
          test: /[\\/]node_modules[\\/]/,
          chunks: 'async',
          name: 'async-vendors',
        },
      },
    },
  },
};

# 9. Preloading
# webpack.config.js
module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html',
      preload: {
        rel: 'preload',
        as: 'script',
        href: 'runtime.js',
      },
    }),
  ],
};

# 10. Compression
# webpack.config.js
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  plugins: [
    new CompressionPlugin({
      algorithm: 'gzip',
      test: /\.(js|css|html|svg)$/,
      threshold: 8192,
      minRatio: 0.8,
    }),
  ],
};

Code Splitting Strategies

Advanced Code Splitting

Code Splitting Strategies
# Code Splitting Strategies

# 1. Route-based Splitting
# App.js
import React, { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
const Contact = lazy(() => import('./pages/Contact'));

function App() {
  return (
    
      Loading...
}> } /> } /> } /> ); } # 2. Component-based Splitting # Component.js import React, { lazy, Suspense } from 'react'; const HeavyComponent = lazy(() => import('./HeavyComponent')); function Component() { return ( Loading component...
}> ); } # 3. Library Splitting # webpack.config.js module.exports = { optimization: { splitChunks: { chunks: 'all', cacheGroups: { react: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, name: 'react', chunks: 'all', }, lodash: { test: /[\\/]node_modules[\\/]lodash[\\/]/, name: 'lodash', chunks: 'all', }, }, }, }, }; # 4. Dynamic Imports # utils.js export const loadUtility = () => { return import('./utility').then(module => module.default); }; # 5. Conditional Loading # ConditionalComponent.js import React, { useState, useEffect } from 'react'; function ConditionalComponent({ shouldLoad }) { const [Component, setComponent] = useState(null); useEffect(() => { if (shouldLoad) { import('./HeavyComponent').then(module => { setComponent(() => module.default); }); } }, [shouldLoad]); return Component ? : null; } # 6. Preloading # PreloadComponent.js import React, { useEffect } from 'react'; function PreloadComponent() { useEffect(() => { // Preload component import('./HeavyComponent'); }, []); return
Component loaded
; } # 7. Webpack Magic Comments # Component.js const Component = lazy(() => import(/* webpackChunkName: "component" */ './Component') ); # 8. Bundle Splitting # webpack.config.js module.exports = { optimization: { splitChunks: { chunks: 'all', minSize: 20000, maxSize: 244000, cacheGroups: { default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', priority: -10, chunks: 'all', }, }, }, }, }; # 9. Runtime Splitting # webpack.config.js module.exports = { optimization: { runtimeChunk: 'single', }, }; # 10. CSS Splitting # webpack.config.js const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { plugins: [ new MiniCssExtractPlugin({ filename: '[name].[contenthash].css', chunkFilename: '[id].[contenthash].css', }), ], };

Performance Best Practices

Optimization Guidelines

Best Practices

  • Code splitting
  • Tree shaking
  • Minification
  • Compression
  • Lazy loading
  • Bundle analysis
  • Performance monitoring

Common Mistakes

  • Large bundle sizes
  • Unused dependencies
  • Poor code splitting
  • Missing minification
  • No compression
  • Inefficient imports
  • Poor caching

Summary

Bundle size optimization involves several key components:

Need More Help?

Struggling with bundle size optimization or need help implementing performance improvements? Our performance experts can help you optimize your application.

Get Bundle Optimization Help