Webpack
02 / 03

Webpack Core Concepts

Webpack Core Concepts

Webpack is a static module bundler for JavaScript applications. It builds a dependency graph and emits one or more optimized bundles.

Entry, Output & Resolve

const path = require('path');

module.exports = {
  mode: 'development',            // 'development' | 'production' | 'none'

  // Entry — one or multiple starting points
  entry: {
    main: './src/index.tsx',
    admin: './src/admin/index.tsx',
  },
  // Single entry shorthand: entry: './src/index.tsx'

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash:8].js',      // [name] = entry key
    chunkFilename: '[name].[contenthash:8].chunk.js',
    assetModuleFilename: 'assets/[hash][ext][query]',
    clean: true,                  // remove dist before each build
    publicPath: '/',              // base URL prefix for all assets
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
    },
    // Prefer ES module fields (tree-shakeable)
    mainFields: ['module', 'browser', 'main'],
  },
};

Loaders — Transform Non-JS Files

module: {
  rules: [
    // TypeScript & JavaScript via Babel
    {
      test: /\.[jt]sx?$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          cacheDirectory: true,         // cache transforms (speeds up rebuilds)
          presets: [
            ['@babel/preset-env', { targets: '> 0.25%, not dead' }],
            ['@babel/preset-react', { runtime: 'automatic' }],
            '@babel/preset-typescript',
          ],
          plugins: ['@babel/plugin-transform-class-properties'],
        },
      },
    },

    // CSS + SCSS + CSS Modules
    {
      test: /\.(css|scss)$/,
      use: [
        isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
        {
          loader: 'css-loader',
          options: {
            modules: {
              auto: true,               // enable CSS Modules for *.module.css
              localIdentName: isDev
                ? '[name]__[local]'
                : '[hash:base64:5]',
            },
            importLoaders: 2,
          },
        },
        'postcss-loader',               // Tailwind, autoprefixer
        'sass-loader',
      ],
    },

    // Static assets — webpack 5 Asset Modules (no file-loader/url-loader needed)
    {
      test: /\.(png|jpg|gif|webp|avif|svg)$/i,
      type: 'asset',                    // auto: inline <8KB, file >=8KB
      parser: { dataUrlCondition: { maxSize: 8 * 1024 } },
    },
    {
      test: /\.(woff2?|eot|ttf|otf)$/i,
      type: 'asset/resource',           // always emit as file
    },
  ],
}

Plugins

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

plugins: [
  // Generate index.html with injected script/link tags
  new HtmlWebpackPlugin({
    template: './public/index.html',
    favicon: './public/favicon.ico',
    minify: !isDev,
  }),

  // Extract CSS into separate files (production)
  !isDev && new MiniCssExtractPlugin({
    filename: '[name].[contenthash:8].css',
    chunkFilename: '[name].[contenthash:8].chunk.css',
  }),

  // Inject env vars as global constants
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
    __APP_VERSION__: JSON.stringify(require('./package.json').version),
  }),

  // Progress output during build
  new webpack.ProgressPlugin(),

  // Bundle visualizer — set ANALYZE=true to enable
  process.env.ANALYZE && new BundleAnalyzerPlugin({
    analyzerMode: 'static',
    openAnalyzer: true,
  }),
].filter(Boolean),

optimization: {
  minimizer: [
    '...',                          // keep default JS minifier (TerserPlugin)
    new CssMinimizerPlugin(),
  ],
}

DevServer

devServer: {
  port: 3000,
  open: true,
  hot: true,                      // HMR
  compress: true,                 // gzip compression
  historyApiFallback: true,       // SPA — serve index.html for 404s
  static: {
    directory: path.join(__dirname, 'public'),
  },
  proxy: [
    {
      context: ['/api', '/auth'],
      target: 'http://localhost:4000',
      changeOrigin: true,
    },
  ],
  // HTTPS with self-signed cert
  // server: 'https',
  client: {
    overlay: { errors: true, warnings: false },
    progress: true,
  },
},

// Source maps
devtool: isDev ? 'eval-cheap-module-source-map' : 'source-map',
// eval-cheap-module-source-map — fast rebuilds, good error messages (dev)
// source-map                   — full source maps (prod, slower)
// hidden-source-map            — no browser exposure (prod + Sentry)

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free