Webpack - Quick Reference

SkillAI & models

Webpack module bundler. Covers configuration, loaders, plugins, optimization. Use when working with Webpack-based projects or migrating from Webpack.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Webpack - Quick Reference skill

What this skill tells your AI

The instructions your AI receives, as published by claude-dev-suite/claude-dev-suite in skills/build-tools/webpack/SKILL.md and read by ahel’s review.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: webpack for comprehensive documentation.

When NOT to Use This Skill

  • New projects - Prefer Vite for better DX and speed
  • Simple bundling - Use esbuild for faster builds
  • Vite/Parcel projects - They have simpler configuration
  • Library builds - Rollup or esbuild are better suited

When to Use This Skill

  • Legacy projects with Webpack
  • Complex build configurations
  • Migration from Webpack to Vite
  • Fine-tuning bundle optimization

Basic Configuration

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

module.exports = {
  mode: 'production', // 'development' | 'production'
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    clean: true,
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
    }),
  ],
};

Loaders

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

      // CSS
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader'],
      },

      // CSS Modules
      {
        test: /\.module\.css$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: {
                localIdentName: '[name]__[local]--[hash:base64:5]',
              },
            },
          },
        ],
      },

      // SASS/SCSS
      {
        test: /\.s[ac]ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },

      // Images
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024, // 8KB inline
          },
        },
      },

      // Fonts
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
      },
    ],
  },
};

Plugins

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const Dotenv = require('dotenv-webpack');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),

    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css',
    }),

    new CopyWebpackPlugin({
      patterns: [{ from: 'public', to: '' }],
    }),

    new Dotenv({
      systemvars: true,
    }),

    // Only in analyze mode
    process.env.ANALYZE && new BundleAnalyzerPlugin(),
  ].filter(Boolean),
};

Code Splitting

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
        react: {
          test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
          name: 'react',
          chunks: 'all',
          priority: 10,
        },
      },
    },
    runtimeChunk: 'single',
  },
};

Dynamic Imports

// Lazy loading
const AdminPanel = React.lazy(() => import('./AdminPanel'));

// Named chunks
const Dashboard = React.lazy(() =>
  import(/* webpackChunkName: "dashboard" */ './Dashboard')
);

// Prefetch (load during idle)
import(/* webpackPrefetch: true */ './HeavyComponent');

// Preload (load in parallel)
import(/* webpackPreload: true */ './CriticalComponent');

Resolve Configuration

module.exports = {
  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils'),
    },
    fallback: {
      // Node.js polyfills for browser
      path: require.resolve('path-browserify'),
      crypto: require.resolve('crypto-browserify'),
    },
  },
};

Dev Server

module.exports = {
  devServer: {
    port: 3000,
    hot: true,
    open: true,
    historyApiFallback: true,  // SPA routing
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        pathRewrite: { '^/api': '' },
      },
    },
    static: {
      directory: path.join(__dirname, 'public'),
    },
    client: {
      overlay: {
        errors: true,
        warnings: false,
      },
    },
  },
};

Production Optimization

const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  mode: 'production',
  devtool: 'source-map',
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true,
            drop_debugger: true,
          },
        },
      }),
      new CssMinimizerPlugin(),
    ],
    splitChunks: {
      chunks: 'all',
      maxSize: 244000, // 244KB max chunk
    },
  },
  plugins: [
    new CompressionPlugin({
      algorithm: 'gzip',
      test: /\.(js|css|html|svg)$/,
    }),
  ],
  performance: {
    maxEntrypointSize: 250000,
    maxAssetSize: 250000,
    hints: 'warning',
  },
};

Environment-based Config

// webpack.config.js
module.exports = (env, argv) => {
  const isProd = argv.mode === 'production';

  return {
    mode: argv.mode,
    devtool: isProd ? 'source-map' : 'eval-cheap-module-source-map',
    output: {
      filename: isProd ? '[name].[contenthash].js' : '[name].js',
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            isProd ? MiniCssExtractPlugin.loader : 'style-loader',
            'css-loader',
          ],
        },
      ],
    },
  };
};

Multiple Configs

// webpack.common.js
module.exports = { /* shared config */ };

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

module.exports = merge(common, {
  mode: 'development',
  devtool: 'eval-cheap-module-source-map',
});

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

module.exports = merge(common, {
  mode: 'production',
  devtool: 'source-map',
});

TypeScript Configuration

module.exports = {
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
};
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["src"]
}

Migration to Vite

// Webpack → Vite mapping
// webpack.config.js         → vite.config.ts
// entry                     → Automatic (index.html)
// output                    → build.outDir
// module.rules              → Plugins (most automatic)
// resolve.alias             → resolve.alias
// devServer.proxy           → server.proxy
// DefinePlugin              → define
// HtmlWebpackPlugin         → Built-in
// MiniCssExtractPlugin      → Built-in
// splitChunks               → build.rollupOptions.output.manualChunks

Debugging

# Verbose output
webpack --stats verbose

# Debug config
webpack --config-name main --debug

# Analyze bundle
npx webpack-bundle-analyzer dist/stats.json

Anti-Patterns to Avoid

  • Do not use file-loader/url-loader (use asset modules)
  • Do not forget contenthash for cache busting
  • Do not overuse aliases (complicates debugging)
  • Do not ignore bundle size warnings

Anti-Patterns

Anti-PatternWhy It's BadCorrect Approach
Using file-loader/url-loaderDeprecatedUse asset modules (type: 'asset')
No contenthash in filenamesCache busting failsUse [contenthash] in output
Not splitting vendor codeLarge bundlesConfigure splitChunks
Missing source maps in prodHard to debugEnable source-map in production
Synchronous imports for routesLarge initial bundleUse dynamic import() for routes
No bundle analysisUnknown bundle compositionUse webpack-bundle-analyzer

Quick Troubleshooting

IssueCauseSolution
Slow buildsNo cachingEnable cache: { type: 'filesystem' }
Large bundle sizeNo code splittingConfigure optimization.splitChunks
Memory errorsLarge projectIncrease Node memory: --max-old-space-size=4096
HMR not workingIncorrect configCheck hot: true and WebSocket settings
Module not foundWrong resolve pathsCheck resolve.modules and resolve.extensions
CSS not extractedMissing pluginUse MiniCssExtractPlugin

Common Issues

IssueSolution
Slow buildsUse cache: { type: 'filesystem' }
Large bundlesEnable splitChunks, tree shaking
Memory issuesUse --max-old-space-size=4096
HMR not workingCheck hot: true, WebSocket proxy

Monitoring Metrics

MetricTarget
Initial bundle< 200KB gzip
Build time (prod)< 60s
Build time (dev)< 10s
Chunks< 10

Checklist

  • Production mode configured
  • Source maps enabled
  • Code splitting with splitChunks
  • CSS extraction (MiniCssExtractPlugin)
  • Assets optimization
  • Compression (gzip/brotli)
  • Bundle analysis
  • Cache configuration

Further Reading

For advanced configurations: mcp__documentation__fetch_docs

Signals

GitHub stars
33
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
webpack
Source
github.com/claude-dev-suite/claude-dev-suite