SalakCode SalakCode
Bundling

Webpack

Module bundler for modern JavaScript

Intermediate
bundling webpack build configuration

Definition

Webpack is a static module bundler for modern JavaScript applications. It builds a dependency graph of your application, processing and bundling modules into optimized output files for deployment.

Core Concepts

Entry, Output, Loaders, Plugins

// webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // Entry point
  entry: './src/index.js',
  
  // Output configuration
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash:8].js',
    clean: true
  },
  
  // Module rules (loaders)
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: 'babel-loader'
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(png|svg|jpg)$/,
        type: 'asset/resource'
      }
    ]
  },
  
  // Plugins
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html'
    })
  ]
};

Loaders

JavaScript (Babel)

module: {
  rules: [
    {
      test: /\.(js|jsx)$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-react', '@babel/preset-env']
        }
      }
    }
  ]
}

CSS

module: {
  rules: [
    {
      test: /\.css$/,
      use: [
        'style-loader', // Injects CSS into DOM
        'css-loader',   // Resolves CSS imports
        'postcss-loader' // Process CSS with PostCSS
      ]
    },
    {
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        'sass-loader'   // Compiles Sass to CSS
      ]
    }
  ]
}

TypeScript

module: {
  rules: [
    {
      test: /\.tsx?$/,
      use: 'ts-loader',
      exclude: /node_modules/
    }
  ]
},
resolve: {
  extensions: ['.tsx', '.ts', '.js']
}

Plugins

Common Plugins

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    // Generate HTML file
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: true
    }),
    
    // Extract CSS to separate files
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css'
    }),
    
    // Clean dist folder before build
    new CleanWebpackPlugin(),
    
    // Analyze bundle size
    new BundleAnalyzerPlugin()
  ]
};

Code Splitting

Dynamic Imports

// Automatic code splitting
const AdminPanel = lazy(() => import('./AdminPanel'));

// webpack creates separate chunk for AdminPanel

Split Chunks

optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all'
      },
      common: {
        minChunks: 2,
        chunks: 'all',
        enforce: true
      }
    }
  }
}

Development Configuration

DevServer

module.exports = {
  mode: 'development',
  
  devtool: 'eval-source-map',
  
  devServer: {
    static: './dist',
    hot: true,
    open: true,
    port: 3000,
    proxy: {
      '/api': 'http://localhost:8080'
    }
  }
};

Environment-Specific Configs

// webpack.common.js - Shared config
// webpack.dev.js - Development
// webpack.prod.js - Production

// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');

module.exports = merge(common, {
  mode: 'production',
  
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin(),
      new CssMinimizerPlugin()
    ]
  }
});

Optimization

Tree Shaking

module.exports = {
  mode: 'production',
  
  optimization: {
    usedExports: true,  // Mark unused exports
    sideEffects: false  // Enable tree shaking
  }
};

// In package.json
{
  "sideEffects": [
    "*.css",
    "*.scss"
  ]
}

Caching

output: {
  filename: '[name].[contenthash:8].js',
  chunkFilename: '[name].[contenthash:8].chunk.js'
},

optimization: {
  moduleIds: 'deterministic',
  runtimeChunk: 'single',
  splitChunks: {
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all'
      }
    }
  }
}

Module Resolution

Aliases

resolve: {
  alias: {
    '@': path.resolve(__dirname, 'src/'),
    '@components': path.resolve(__dirname, 'src/components/'),
    '@utils': path.resolve(__dirname, 'src/utils/')
  }
}

// Usage
import Button from '@components/Button';
import { formatDate } from '@utils/date';

Best Practices

Performance Budgets

performance: {
  hints: 'error',
  maxEntrypointSize: 250000,
  maxAssetSize: 250000
}

Analyzing Bundle

# Generate stats file
webpack --profile --json > stats.json

# Analyze online
npx webpack-bundle-analyzer stats.json
Key Takeaway

Webpack is powerful but complex. Configure loaders for different file types, use plugins for optimization, implement code splitting for performance, and leverage caching with content hashes. Consider migrating to Vite for new projects, but understanding Webpack remains valuable for maintaining existing codebases.

Resources

Related Topics