Webpack
Webpack 5 setup, optimization, code splitting, and plugin configuration for JavaScript applications
You are an expert in Webpack 5 for JavaScript project bundling, optimization, and build pipeline configuration. ## Key Points - Use `contenthash` in filenames for long-term caching in production builds. - Enable `filesystem` cache for drastically faster rebuilds during development. - Set `sideEffects: false` in package.json to enable aggressive tree shaking. - Use `splitChunks` to extract vendor code into a separate cacheable chunk. - Prefer Webpack 5 asset modules (`type: 'asset'`) over `file-loader` and `url-loader`. - Use `resolve.extensions` to avoid writing file extensions in imports. - **Stale filesystem cache**: When updating loaders or plugins, increment the `cache.version` or clear `.cache/` to avoid stale build artifacts. - **Over-splitting chunks**: Too many small chunks increase HTTP requests. Use `minSize` and `maxAsyncRequests` in `splitChunks` to control granularity. - **Missing contenthash in dev**: Using `contenthash` in development mode slows down builds. Only apply it for production. - **Tree shaking not working**: Ensure you are using ES module syntax (`import`/`export`), not CommonJS. Check `sideEffects` in package.json of dependencies. - **Large source maps in production**: Use `source-map` for production (separate file) and `eval-cheap-module-source-map` for development (fast rebuild, inlined). ## Quick Example ```bash npm install --save-dev webpack webpack-cli webpack-dev-server npm install --save-dev html-webpack-plugin mini-css-extract-plugin css-loader npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react ``` ```js const LazyComponent = React.lazy(() => import(/* webpackChunkName: "feature" */ './Feature') ); ```
skilldb get build-tools-skills/WebpackFull skill: 173 linesWebpack — Build Tools
You are an expert in Webpack 5 for JavaScript project bundling, optimization, and build pipeline configuration.
Core Philosophy
Overview
Webpack is a highly configurable module bundler that processes JavaScript applications by building a dependency graph and emitting optimized bundles. Version 5 introduced Module Federation, persistent caching, improved tree shaking, and asset modules that replace older loaders for common file types.
Setup & Configuration
Installation
npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save-dev html-webpack-plugin mini-css-extract-plugin css-loader
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/preset-react
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = (env, argv) => {
const isProd = argv.mode === 'production';
return {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: isProd ? '[name].[contenthash].js' : '[name].js',
clean: true,
},
devtool: isProd ? 'source-map' : 'eval-cheap-module-source-map',
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
proxy: [{ context: ['/api'], target: 'http://localhost:8080' }],
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: 'babel-loader',
},
{
test: /\.css$/,
use: [isProd ? MiniCssExtractPlugin.loader : 'style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|gif|woff2?)$/,
type: 'asset',
parser: { dataUrlCondition: { maxSize: 8 * 1024 } },
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: './public/index.html' }),
isProd && new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
].filter(Boolean),
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
alias: { '@': path.resolve(__dirname, 'src') },
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
cache: {
type: 'filesystem',
},
};
};
Core Patterns
Code Splitting with Dynamic Imports
const LazyComponent = React.lazy(() =>
import(/* webpackChunkName: "feature" */ './Feature')
);
Module Federation
const { ModuleFederationPlugin } = require('webpack').container;
new ModuleFederationPlugin({
name: 'host',
remotes: {
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
});
Bundle Analysis
npm install --save-dev webpack-bundle-analyzer
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// Add to plugins array:
new BundleAnalyzerPlugin({ analyzerMode: 'static', openAnalyzer: false });
Persistent Caching
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
version: '1.0',
},
Best Practices
- Use
contenthashin filenames for long-term caching in production builds. - Enable
filesystemcache for drastically faster rebuilds during development. - Set
sideEffects: falsein package.json to enable aggressive tree shaking. - Use
splitChunksto extract vendor code into a separate cacheable chunk. - Prefer Webpack 5 asset modules (
type: 'asset') overfile-loaderandurl-loader. - Use
resolve.extensionsto avoid writing file extensions in imports.
Common Pitfalls
- Stale filesystem cache: When updating loaders or plugins, increment the
cache.versionor clear.cache/to avoid stale build artifacts. - Over-splitting chunks: Too many small chunks increase HTTP requests. Use
minSizeandmaxAsyncRequestsinsplitChunksto control granularity. - Missing contenthash in dev: Using
contenthashin development mode slows down builds. Only apply it for production. - Tree shaking not working: Ensure you are using ES module syntax (
import/export), not CommonJS. ChecksideEffectsin package.json of dependencies. - Large source maps in production: Use
source-mapfor production (separate file) andeval-cheap-module-source-mapfor development (fast rebuild, inlined).
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add build-tools-skills
Related Skills
Biome
Biome linter, formatter, and code analysis configuration for JavaScript and TypeScript projects
Esbuild
esbuild bundling, transpilation, and build scripting for ultra-fast JavaScript builds
Eslint Prettier
ESLint and Prettier combined setup for JavaScript and TypeScript linting and formatting
Rollup
Rollup configuration for building JavaScript libraries with tree shaking and multiple output formats
Swc
SWC compiler configuration for fast TypeScript and JavaScript transpilation and minification
Tsconfig
TypeScript compiler configuration, project references, and tsconfig best practices