Webpack Cheat Sheet
Webpack bundles modules by building a dependency graph from entry points, transforming files with loaders and applying plugins for optimization and environment-specific behavior.
How to use this Webpack cheat sheet Every Webpack build starts with entry and output, then chains loaders (transform) and plugins (side effects). Mode toggles defaults: development favors fast rebuilds and source maps; production enables minification, tree shaking, and long-term caching via content hashes.
Resolve aliases shorten imports; splitChunks extracts vendor code; devServer proxies API calls during local work. Production builds benefit from deterministic module IDs, runtime chunk separation, and analyzing bundle size before shipping.
Quick Webpack example const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
module: {
rules: [
{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
],
},
plugins: [new HtmlWebpackPlugin({ template: './public/index.html' })],
devServer: { port: 3000, hot: true, historyApiFallback: true },
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
}; Entry & Output Option Example Notes entry entry: "./src/main.ts" Starting point(s) for the dependency graph output.path path.resolve(__dirname, "dist") Absolute directory for emitted assets output.filename "[name].[contenthash].js" Hash enables cache busting in production output.clean clean: true Removes old assets before each build (Webpack 5+) output.publicPath publicPath: "/assets/" Prefix for on-demand loaded chunks output.assetModuleFilename "images/[hash][ext]" Pattern for imported files (Webpack 5 asset modules) Multiple entries entry: { app: "./app.js", admin: "./admin.js" } Separate bundles per entry name Library output library: { type: "module" } Expose bundle as ES module for federation or CDN
Common Loaders Rule Example Purpose Babel { test: /\.jsx?$/, use: "babel-loader" } Transpile modern JS/TS for target browsers TypeScript use: "ts-loader" or babel-loader + preset Compile .ts/.tsx files CSS use: ["style-loader", "css-loader"] Inject CSS in dev; extract in prod with MiniCssExtractPlugin Sass use: ["css-loader", "sass-loader"] Compile SCSS to CSS Assets { type: "asset/resource" } Emit file and return URL (Webpack 5) Inline SVG { type: "asset/inline" } Embed small assets as data URLs JSON { type: "json" } Import JSON as ES module (default in Webpack 5) Rule order use: [{ loader: "css-loader" }, { loader: "postcss-loader" }] Loaders run right-to-left (bottom-up)
Plugins & Optimization Plugin / Option Example Purpose HtmlWebpackPlugin new HtmlWebpackPlugin({ template: "index.html" }) Inject script tags into HTML DefinePlugin new DefinePlugin({ "process.env.API": JSON.stringify(url) }) Replace env vars at build time MiniCssExtractPlugin new MiniCssExtractPlugin({ filename: "[name].[contenthash].css" }) Extract CSS to separate files in production splitChunks optimization: { splitChunks: { chunks: "all" } } Vendor and async code splitting runtimeChunk optimization: { runtimeChunk: "single" } Isolate webpack runtime for stable vendor hashes TerserPlugin new TerserPlugin({ parallel: true }) Minify JS (default in production mode) BundleAnalyzer new BundleAnalyzerPlugin() Visualize bundle composition mode mode: "production" Enables minification, tree shaking, and built-in optimizations
Resolve & DevServer Option Example Notes alias resolve: { alias: { "@": path.resolve("src") } } Shorten import paths extensions extensions: [".ts", ".tsx", ".js"] Try extensions when import omits suffix modules modules: [path.resolve("src"), "node_modules"] Resolve modules from src first devServer.port devServer: { port: 8080 } Local dev server port devServer.proxy proxy: { "/api": "http://localhost:4000" } Forward API requests during dev devServer.hot hot: true Hot Module Replacement without full reload devServer.historyApiFallback historyApiFallback: true SPA fallback to index.html devServer.static static: { directory: path.join(__dirname, "public") } Serve static files alongside bundled assets
Environment-specific configs module.exports = (env, argv) => ({
mode: argv.mode,
devtool: argv.mode === 'production' ? 'source-map' : 'eval-cheap-module-source-map',
optimization: {
minimize: argv.mode === 'production',
splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /node_modules/, name: 'vendors' } } },
},
}); Export a function to branch on CLI mode and env flags.
Dynamic import code splitting button.addEventListener('click', () => {
import(/* webpackChunkName: "chart" */ './chart.js')
.then(({ renderChart }) => renderChart(data));
}); Magic comments name chunks; Webpack emits separate async bundles.
Production cache headers pattern output: {
filename: '[name].[contenthash:8].js',
chunkFilename: '[name].[contenthash:8].js',
},
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',
}, Content hashes plus runtime chunk keep vendor bundles cacheable across deploys.
Common mistakes Forgetting to exclude node_modules from babel-loader, slowing builds dramatically. Using style-loader in production instead of MiniCssExtractPlugin, blocking render. Setting publicPath incorrectly so lazy-loaded chunks 404 in production. Disabling splitChunks and shipping one giant bundle with poor cache efficiency. Key takeaways Entry defines the graph; output.filename with contenthash enables long-term caching. Loaders transform; plugins orchestrate side effects and optimization. splitChunks and runtimeChunk separate vendor code from app code. devServer proxy and HMR keep local development fast without CORS hacks.
Pro Tip
Run webpack-bundle-analyzer before every major release—most bundle bloat comes from a handful of accidental full-library imports.
Common Webpack Mistakes Go to next item