Skip to main content
๐Ÿ“ฆintermediate

Webpack

Webpack is the most battle-tested JavaScript bundler. Learn its core concepts: entry, output, loaders, plugins, and how to configure it for real projects.

What is Webpack?

Webpack is a static module bundler. It builds a dependency graph from an entry point and packages everything into one or more bundles.

Entry (index.js) โ†’ App.jsx (depends on) โ†’ Button.jsx โ†’ styles.css โ†’ logo.svg โ†’ api.js โ†’ node_modules/axios Output: dist/main.js + dist/styles.css

Core Concepts

Entry

The starting point of the dependency graph:

hljs javascript
// webpack.config.js
module.exports = {
  entry: "./src/index.js",

  // Multiple entry points
  entry: {
    main: "./src/index.js",
    admin: "./src/admin.js",
  },
};

Output

Where to put the bundles:

hljs javascript
const path = require("path");

module.exports = {
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "[name].[contenthash].js", // hash for cache busting
    clean: true, // clean dist before each build
  },
};

Mode

hljs javascript
module.exports = {
  mode: "development",   // fast builds, readable output, source maps
  // mode: "production", // minified, tree-shaken, optimized
  // mode: "none",       // no defaults
};

Loaders

Loaders transform non-JavaScript files:

hljs javascript
module.exports = {
  module: {
    rules: [
      // JavaScript/TypeScript
      {
        test: /\.(js|jsx|ts|tsx)$/,
        use: "babel-loader",
        exclude: /node_modules/,
      },
      // CSS
      {
        test: /\.css$/,
        use: [
          "style-loader",  // injects CSS into DOM
          "css-loader",    // resolves CSS imports
        ],
      },
      // SCSS
      {
        test: /\.scss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      // Images
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: "asset/resource",
        generator: {
          filename: "images/[hash][ext]",
        },
      },
      // Fonts
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: "asset/resource",
      },
    ],
  },
};

Plugins

Plugins do everything loaders can't:

hljs javascript
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  plugins: [
    // Generate index.html from template
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      title: "My App",
    }),
    // Extract CSS to separate file (for production)
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
    }),
  ],
};

Full Example Config

A typical React project config:

hljs javascript
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const isDev = process.env.NODE_ENV !== "production";

module.exports = {
  mode: isDev ? "development" : "production",
  entry: "./src/index.jsx",

  output: {
    path: path.resolve(__dirname, "dist"),
    filename: isDev ? "[name].js" : "[name].[contenthash].js",
    publicPath: "/",
    clean: true,
  },

  resolve: {
    extensions: [".js", ".jsx", ".ts", ".tsx"], // try these extensions
    alias: {
      "@": path.resolve(__dirname, "src"), // @/components โ†’ src/components
    },
  },

  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env", "@babel/preset-react"],
          },
        },
      },
      {
        test: /\.css$/,
        use: [
          isDev ? "style-loader" : MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: { modules: true }, // CSS Modules
          },
        ],
      },
    ],
  },

  plugins: [
    new HtmlWebpackPlugin({ template: "./public/index.html" }),
    !isDev && new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
    }),
  ].filter(Boolean),

  devServer: {
    port: 3000,
    hot: true,         // HMR
    historyApiFallback: true, // SPA routing
    open: true,
  },

  optimization: {
    splitChunks: {
      chunks: "all", // separate vendor chunk
    },
  },

  devtool: isDev ? "eval-source-map" : "source-map",
};

Hot Module Replacement (HMR)

HMR updates modules in the browser without a full reload:

hljs javascript
// webpack automatically handles HMR for CSS
// For JS modules, you can handle updates manually:
if (module.hot) {
  module.hot.accept("./App", () => {
    // re-render when App.js changes
    const NextApp = require("./App").default;
    ReactDOM.render(<NextApp />, document.getElementById("root"));
  });
}

React Refresh (used by Create React App, Next.js) handles this automatically.

Webpack Bundle Analyzer

Visualize what's in your bundle:

hljs javascript
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    process.env.ANALYZE && new BundleAnalyzerPlugin(),
  ].filter(Boolean),
};

Run with ANALYZE=true npm run build to open an interactive treemap.

Common Optimizations

hljs javascript
module.exports = {
  optimization: {
    // Split vendor code (node_modules) into separate chunk
    splitChunks: {
      chunks: "all",
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: "vendors",
          chunks: "all",
        },
      },
    },

    // Use module IDs based on content hash (stable across builds)
    moduleIds: "deterministic",

    // Tree shaking
    usedExports: true,

    // Minify
    minimize: true,
  },
};
โ–ถTry it yourself

Key Takeaways

  • Webpack 5 key concepts: entry, output, loaders, plugins, mode
  • Loaders transform files (JS, CSS, images); plugins do everything else
  • mode: "production" automatically enables tree shaking and minification
  • splitChunks separates vendor code for better caching
  • HMR (Hot Module Replacement) speeds up development
  • Use bundle analyzer to find what's taking up space

Ready to test your knowledge?

Take a quiz on what you just learned.

Take the Quiz โ†’