Webpack Cheatsheet¶
Webpack - Static Module Bundler
Webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph from one or more entry points and then combines every module your project needs into one or more bundles.
Table of Contents¶
- Installation
- Basic Configuration
- Entry Points
- Output
- Loaders
- Plugins
- Mode
- Development Server
- Code Splitting
- Optimization
- Module Resolution
- Hot Module Replacement
- Environment Variables
- Production Build
- Advanced Configuration
- Performance
- Troubleshooting
- Best Practices
Installation¶
Global Installation¶
Local Installation (Recommended)¶
# Initialize npm project
npm init -y
# Install webpack locally
npm install --save-dev webpack webpack-cli
# Install webpack dev server
npm install --save-dev webpack-dev-server
# Install common loaders and plugins
npm install --save-dev html-webpack-plugin css-loader style-loader file-loader url-loader
Package.json Scripts¶
{
"scripts": {
"build": "webpack --mode production",
"dev": "webpack --mode development",
"start": "webpack serve --mode development",
"watch": "webpack --mode development --watch"
}
}
Basic Configuration¶
Minimal webpack.config.js¶
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Complete Basic Configuration¶
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
};
TypeScript Configuration¶
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Entry Points¶
Single Entry Point¶
Multiple Entry Points¶
Dynamic Entry Points¶
Entry with Dependencies¶
module.exports = {
entry: {
main: {
import: './src/index.js',
dependOn: 'shared'
},
admin: {
import: './src/admin.js',
dependOn: 'shared'
},
shared: 'lodash'
}
};
Output¶
Basic Output Configuration¶
const path = require('path');
module.exports = {
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Multiple Entry Output¶
module.exports = {
entry: {
main: './src/index.js',
admin: './src/admin.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Output with Hashing¶
module.exports = {
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true
}
};
Public Path Configuration¶
module.exports = {
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/assets/'
}
};
Library Output¶
module.exports = {
output: {
filename: 'my-library.js',
path: path.resolve(__dirname, 'dist'),
library: {
name: 'MyLibrary',
type: 'umd'
}
}
};
Loaders¶
CSS Loaders¶
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.less$/i,
use: ['style-loader', 'css-loader', 'less-loader']
}
]
}
};
JavaScript Loaders¶
module.exports = {
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
};
File Loaders¶
module.exports = {
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource'
},
{
test: /\.(csv|tsv)$/i,
use: ['csv-loader']
},
{
test: /\.xml$/i,
use: ['xml-loader']
}
]
}
};
Asset Modules¶
module.exports = {
module: {
rules: [
{
test: /\.png/,
type: 'asset/resource'
},
{
test: /\.html/,
type: 'asset/resource'
},
{
test: /\.txt/,
type: 'asset/source'
},
{
test: /\.jpg/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 // 4kb
}
}
}
]
}
};
Loader Options¶
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true
}
}
]
}
]
}
};
Plugins¶
HTML Webpack Plugin¶
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
inject: 'body'
})
]
};
Extract CSS Plugin¶
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
]
};
Define Plugin¶
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
'process.env.API_URL': JSON.stringify('https://api.example.com')
})
]
};
Copy Webpack Plugin¶
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'public', to: 'public' },
{ from: 'assets/images', to: 'images' }
]
})
]
};
Bundle Analyzer Plugin¶
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'static',
openAnalyzer: false
})
]
};
Clean Webpack Plugin¶
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin()
]
};
Mode¶
Development Mode¶
Production Mode¶
Mode-specific Configuration¶
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
mode: argv.mode,
devtool: isProduction ? 'source-map' : 'eval-source-map',
optimization: {
minimize: isProduction
}
};
};
Development Server¶
Basic Dev Server¶
Advanced Dev Server Configuration¶
module.exports = {
devServer: {
static: {
directory: path.join(__dirname, 'dist')
},
compress: true,
port: 3000,
hot: true,
open: true,
historyApiFallback: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
};
HTTPS Dev Server¶
module.exports = {
devServer: {
https: true,
// or with custom certificates
https: {
key: fs.readFileSync('/path/to/server.key'),
cert: fs.readFileSync('/path/to/server.crt'),
ca: fs.readFileSync('/path/to/ca.pem')
}
}
};
Code Splitting¶
Entry Point Splitting¶
Dynamic Imports¶
// In your JavaScript code
import('./math.js').then(math => {
console.log(math.add(16, 26));
});
// Or with async/await
async function loadMath() {
const math = await import('./math.js');
return math.add(16, 26);
}
SplitChunks Plugin¶
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
common: {
name: 'common',
minChunks: 2,
chunks: 'all',
enforce: true
}
}
}
}
};
Advanced Code Splitting¶
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
minSize: 20000,
maxSize: 244000,
cacheGroups: {
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
},
vendor: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true
},
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
chunks: 'all'
}
}
}
}
};
Optimization¶
Minification¶
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true
}
}
})
]
}
};
CSS Optimization¶
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin()
]
}
};
Tree Shaking¶
Runtime Chunk¶
Module Concatenation¶
Module Resolution¶
Resolve Configuration¶
const path = require('path');
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
'components': path.resolve(__dirname, 'src/components'),
'utils': path.resolve(__dirname, 'src/utils')
},
modules: [
'node_modules',
path.resolve(__dirname, 'src')
]
}
};
Resolve Fallback¶
module.exports = {
resolve: {
fallback: {
"fs": false,
"path": require.resolve("path-browserify"),
"crypto": require.resolve("crypto-browserify")
}
}
};
Hot Module Replacement¶
Enable HMR¶
const webpack = require('webpack');
module.exports = {
devServer: {
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
HMR in Code¶
// In your JavaScript modules
if (module.hot) {
module.hot.accept('./library.js', function() {
console.log('Accepting the updated library module!');
// Re-render or update your app
});
}
React Hot Reload¶
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
plugins: ['react-refresh/babel']
}
}
]
}
]
},
plugins: [
new ReactRefreshWebpackPlugin()
]
};
Environment Variables¶
DefinePlugin for Environment Variables¶
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.API_URL': JSON.stringify(process.env.API_URL || 'http://localhost:3000')
})
]
};
Environment-specific Configuration¶
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
mode: argv.mode,
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(argv.mode),
'process.env.API_URL': JSON.stringify(
isProduction ? 'https://api.production.com' : 'http://localhost:3000'
)
})
]
};
};
DotEnv Plugin¶
const Dotenv = require('dotenv-webpack');
module.exports = {
plugins: [
new Dotenv({
path: './.env',
safe: true,
systemvars: true
})
]
};
Production Build¶
Production Configuration¶
const path = require('path');
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');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
}
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true
}
}
}),
new CssMinimizerPlugin()
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
},
runtimeChunk: 'single'
}
};
Build Scripts¶
{
"scripts": {
"build": "webpack --mode production",
"build:analyze": "webpack --mode production --env analyze",
"build:stats": "webpack --mode production --json > stats.json"
}
}
Advanced Configuration¶
Multi-page Application¶
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
home: './src/home.js',
about: './src/about.js',
contact: './src/contact.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'home.html',
template: './src/home.html',
chunks: ['home']
}),
new HtmlWebpackPlugin({
filename: 'about.html',
template: './src/about.html',
chunks: ['about']
}),
new HtmlWebpackPlugin({
filename: 'contact.html',
template: './src/contact.html',
chunks: ['contact']
})
]
};
Micro-frontends Configuration¶
const ModuleFederationPlugin = require('@module-federation/webpack');
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'shell',
remotes: {
mfe1: 'mfe1@http://localhost:3001/remoteEntry.js',
mfe2: 'mfe2@http://localhost:3002/remoteEntry.js'
}
})
]
};
Progressive Web App¶
const WorkboxPlugin = require('workbox-webpack-plugin');
module.exports = {
plugins: [
new WorkboxPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: true
})
]
};
Custom Loaders¶
// custom-loader.js
module.exports = function(source) {
// Transform the source
return `export default ${JSON.stringify(source)}`;
};
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.custom$/,
use: path.resolve(__dirname, 'custom-loader.js')
}
]
}
};
Custom Plugins¶
class MyCustomPlugin {
apply(compiler) {
compiler.hooks.emit.tapAsync('MyCustomPlugin', (compilation, callback) => {
console.log('This is an example plugin!');
callback();
});
}
}
module.exports = {
plugins: [
new MyCustomPlugin()
]
};
Performance¶
Performance Budgets¶
module.exports = {
performance: {
maxAssetSize: 250000,
maxEntrypointSize: 250000,
hints: 'warning'
}
};
Lazy Loading¶
// Dynamic imports for lazy loading
const LazyComponent = React.lazy(() => import('./LazyComponent'));
// Webpack magic comments
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
'./modules/my-module.js'
);
Prefetching and Preloading¶
// Prefetch
import(
/* webpackPrefetch: true */
'./modules/LoginModal.js'
);
// Preload
import(
/* webpackPreload: true */
'./modules/ChartingLibrary.js'
);
Bundle Analysis¶
# Generate stats file
webpack --profile --json > stats.json
# Analyze with webpack-bundle-analyzer
npx webpack-bundle-analyzer stats.json
# Use webpack-bundle-analyzer plugin
npm install --save-dev webpack-bundle-analyzer
Troubleshooting¶
Common Issues and Solutions¶
Module Not Found¶
// Check resolve configuration
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
alias: {
'@': path.resolve(__dirname, 'src')
}
}
};
Memory Issues¶
# Increase Node.js memory limit
node --max-old-space-size=4096 node_modules/.bin/webpack
# Or in package.json
{
"scripts": {
"build": "node --max-old-space-size=4096 node_modules/.bin/webpack"
}
}
Slow Build Times¶
module.exports = {
// Use cache
cache: {
type: 'filesystem'
},
// Exclude node_modules from babel-loader
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
},
// Use thread-loader for expensive loaders
module: {
rules: [
{
test: /\.js$/,
use: [
'thread-loader',
'babel-loader'
]
}
]
}
};
Source Map Issues¶
module.exports = {
// Different source map options
devtool: 'eval-source-map', // Development
devtool: 'source-map', // Production
devtool: 'cheap-module-source-map', // Faster builds
devtool: false // No source maps
};
Debugging Configuration¶
module.exports = {
stats: {
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}
};
Best Practices¶
Configuration Organization¶
// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
]
};
// webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devtool: 'eval-source-map',
devServer: {
static: './dist'
}
});
// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map'
});
Performance Optimization¶
- Use production mode for optimizations
- Enable tree shaking to remove dead code
- Split chunks to improve caching
- Use content hashing for long-term caching
- Minimize bundle size with proper loaders and plugins
Development Experience¶
- Use HMR for faster development
- Configure source maps for debugging
- Set up dev server with proxy for API calls
- Use webpack-bundle-analyzer to understand bundle composition
Code Organization¶
- Separate configuration for different environments
- Use aliases for cleaner imports
- Organize loaders by file type
- Group related plugins together
Summary¶
Webpack is a powerful and flexible module bundler that can handle complex build requirements for modern web applications. Key features include:
- Module Bundling: Combines modules into optimized bundles
- Loaders: Transform files during the build process
- Plugins: Extend webpack functionality
- Code Splitting: Split code into smaller chunks for better performance
- Hot Module Replacement: Update modules without full page reload
- Tree Shaking: Remove unused code from bundles
- Asset Management: Handle various file types and assets
By mastering webpack configuration and following best practices, you can create efficient build processes that improve both development experience and application performance.