Webpack 5 配置优化
为什么需要优化
Webpack 是现代前端最常用的构建工具之一。随着项目规模增长,构建时间和产出质量成为关注重点。本文将介绍从开发到生产的全方位优化策略。
开发体验优化
缩小文件搜索范围
// webpack.config.js
module.exports = {
resolve: {
// 只查找这些扩展名
extensions: ['.js', '.jsx', '.ts', '.tsx'],
// 指定模块搜索目录
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
// 别名,减少查找路径
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
};
模块解析优化
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
// 只处理 src 目录
include: path.resolve(__dirname, 'src'),
// 排除 node_modules
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
};
缓存
// 持久化缓存(Webpack 5 内置)
module.exports = {
cache: {
type: 'filesystem', // 文件系统缓存
cacheDirectory: path.resolve(__dirname, '.temp_cache'),
buildDependencies: {
config: [__filename], // 配置变化时失效
},
},
};
构建速度优化
多进程构建
// 安装 thread-loader
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
use: [
'thread-loader', // 放在第一位
'babel-loader',
],
},
],
},
};
使用更快的 loader
// esbuild-loader 替代 babel-loader
const { EsbuildPlugin } = require('esbuild-loader');
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'esbuild-loader',
options: {
loader: 'tsx',
target: 'es2020',
},
},
],
},
optimization: {
minimizer: [
new EsbuildPlugin({
target: 'es2020',
css: true,
}),
],
},
};
产出优化
代码分割
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: 10,
},
common: {
minChunks: 2,
priority: 5,
reuseExistingChunk: true,
},
},
},
},
};
动态导入
// React.lazy + Suspense 自动代码分割
const LazyPage = React.lazy(() => import('./pages/LazyPage'));
// 或者 Webpack 的 import()
function Page() {
const [module, setModule] = useState(null);
useEffect(() => {
import('./heavy-module').then((mod) => setModule(mod.default));
}, []);
}
压缩优化
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
'...', // 保留默认 JS 压缩
new CssMinimizerPlugin(), // CSS 压缩
],
},
};
Tree Shaking
// package.json 中标记 side effects
{
"sideEffects": [
"*.css",
"*.global.js"
]
}
// Webpack 配置确保 production 模式启用 tree shaking
module.exports = {
mode: 'production',
optimization: {
usedExports: true,
sideEffects: true,
},
};
图片和资源优化
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif|svg)$/,
type: 'asset', // 自动选择 inline 或 resource
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // 8KB 以下转为 base64
},
},
generator: {
filename: 'images/[name].[contenthash:8][ext]',
},
},
{
test: /\.(woff2?|eot|ttf)$/,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[contenthash:8][ext]',
},
},
],
},
};
模块联邦(Module Federation)
Webpack 5 的模块联邦可以实现微前端架构:
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Header': './src/components/Header',
'./Footer': './src/components/Footer',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
}),
],
};
生产配置完整示例
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash:8].js',
clean: true,
},
cache: { type: 'filesystem' },
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
alias: { '@': path.resolve(__dirname, 'src') },
},
module: {
rules: [
{ test: /\.tsx?$/, loader: 'esbuild-loader', options: { loader: 'tsx' } },
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'] },
{ test: /\.(png|jpg)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 8 * 1024 } } },
],
},
plugins: [
new HtmlWebpackPlugin({ template: './public/index.html' }),
new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash:8].css' }),
],
optimization: {
splitChunks: { chunks: 'all', cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors' } } },
},
};
总结
优化没有银弹,需要根据项目实际情况选择策略。开发阶段关注构建速度,生产阶段关注产出质量。建议从性能分析(webpack-bundle-analyzer)入手,找到瓶颈后再针对性优化。