Appearance
Webpack 性能优化
Webpack 性能优化是构建高效开发体验和生产环境的关键。本章将详细介绍如何优化 Webpack 的构建速度和输出质量。
构建性能优化
1. 启用缓存
javascript
module.exports = {
cache: {
type: 'filesystem', // 文件系统缓存
buildDependencies: {
config: [__filename] // 配置文件变更时清除缓存
},
cacheDirectory: path.resolve(__dirname, '.webpack-cache'),
name: 'production' // 缓存名称
},
snapshot: {
managedPaths: [ // Webpack 监控的路径
path.resolve(__dirname, 'node_modules')
],
immutablePaths: [ // 不变路径
path.resolve(__dirname, 'immutable-deps')
]
}
};
2. 优化模块解析
javascript
module.exports = {
resolve: {
// 优化模块解析
modules: [
path.resolve(__dirname, 'src'), // 优先查找项目源码
'node_modules' // 然后查找 node_modules
],
// 减少扩展名尝试
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
// 使用别名减少解析时间
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components'),
'@utils': path.resolve(__dirname, 'src/utils')
},
// 解析时的主字段
mainFields: ['browser', 'module', 'main'],
// 解析目录时的主文件
mainFiles: ['index']
},
// 排除不需要解析的模块
module: {
noParse: [
/jquery/, // 不解析 jQuery
/lodash/ // 不解析 Lodash
]
}
};
3. 并行处理优化
javascript
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: require('os').cpus().length, // 使用所有 CPU 核心
extractComments: false
}),
new CssMinimizerPlugin({
parallel: require('os').cpus().length // 并行处理 CSS
})
]
},
// 使用 thread-loader 并行处理
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'thread-loader',
options: {
workers: require('os').cpus().length - 1
}
},
'babel-loader'
],
exclude: /node_modules/
}
]
}
};
开发环境性能优化
1. 选择合适的 devtool
javascript
// 开发环境配置
module.exports = {
mode: 'development',
devtool: 'eval-cheap-module-source-map', // 平衡构建速度和调试体验
// devtool: 'eval' // 构建最快
// devtool: 'eval-source-map' // 调试最佳,但构建慢
};
2. 优化开发服务器配置
javascript
module.exports = {
devServer: {
static: {
directory: path.join(__dirname, 'public'),
watch: {
ignored: [
path.join(__dirname, 'node_modules'),
path.join(__dirname, '.git')
]
}
},
hot: true, // 启用热模块替换
liveReload: false, // 禁用页面自动刷新
client: {
overlay: false // 禁用错误覆盖层
}
}
};
3. 使用持久化缓存
javascript
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
},
version: '1.0.0' // 缓存版本,变更时清除缓存
}
};
生产环境性能优化
1. 代码分割优化
javascript
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
maxInitialRequests: 10,
maxAsyncRequests: 10,
cacheGroups: {
// 第三方库
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'initial',
maxSize: 244000
},
// React 生态
react: {
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
name: 'react',
priority: 20,
chunks: 'initial'
},
// 公共代码
common: {
name: 'common',
minChunks: 2,
priority: 5,
chunks: 'initial',
minSize: 0
}
}
},
// 运行时代码分离
runtimeChunk: {
name: 'runtime'
}
}
};
2. Tree Shaking 优化
javascript
module.exports = {
mode: 'production',
optimization: {
sideEffects: false, // 正确标记副作用
usedExports: true, // 启用标记使用的导出
concatenateModules: true, // 模块串联(Scope Hoisting)
providedExports: true // 提供导出信息
}
};
// 在 package.json 中标记副作用
// {
// "sideEffects": [
// "./src/polyfills.js",
// "*.css"
// ]
// }
3. 动态导入优化
javascript
// 在应用代码中使用动态导入
// src/components/LazyComponent.js
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
// 预加载和预获取
const routes = [
{
path: '/dashboard',
component: React.lazy(() =>
import(/* webpackPreload: true */ './Dashboard')
)
},
{
path: '/profile',
component: React.lazy(() =>
import(/* webpackPrefetch: true */ './Profile')
)
}
];
资源优化
1. 图片和静态资源优化
javascript
module.exports = {
module: {
rules: [
// Webpack 5 资源模块
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024 // 8kb 以下转为 base64
}
},
generator: {
filename: 'images/[name].[contenthash:8][ext]'
}
},
// 字体文件
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[contenthash:8][ext]'
}
}
]
}
};
2. 代码压缩优化
javascript
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true, // 删除 console
drop_debugger: true, // 删除 debugger
pure_funcs: ['console.log'] // 删除特定函数调用
},
mangle: {
properties: {
regex: /^__/ // 混淆以 __ 开头的属性
}
},
format: {
comments: false // 删除注释
}
},
extractComments: false
})
]
}
};
分析和监控
1. 构建分析
javascript
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
// 构建分析
process.env.ANALYZE && new BundleAnalyzerPlugin({
analyzerMode: process.env.NODE_ENV === 'production' ? 'static' : 'server',
openAnalyzer: true,
reportFilename: 'bundle-report.html'
})
].filter(Boolean)
};
2. 性能监控
javascript
module.exports = {
performance: {
maxAssetSize: 250000, // 单个资源最大 250kb
maxEntrypointSize: 250000, // 入口点最大 250kb
hints: 'warning' // 性能警告
},
stats: {
all: false,
modules: false,
maxModules: 0,
errors: true,
warnings: true,
assets: true,
chunks: true,
chunkModules: true
}
};
高级优化技术
1. 模块联邦优化
javascript
const ModuleFederationPlugin = require('webpack').container.ModuleFederationPlugin;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'shell',
remotes: {
mfe1: 'mfe1@http://localhost:3001/remoteEntry.js',
mfe2: 'mfe2@http://localhost:3002/remoteEntry.js'
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true }
}
})
]
};
2. 预加载和预获取
javascript
// 动态导入中的魔法注释
const Dashboard = React.lazy(() =>
import(
/* webpackChunkName: "dashboard" */
/* webpackPreload: true */
'./Dashboard'
)
);
const AdminPanel = React.lazy(() =>
import(
/* webpackChunkName: "admin" */
/* webpackPrefetch: true */
'./AdminPanel'
)
);
3. 条件加载
javascript
// 根据环境条件加载
const loadDevTools = async () => {
if (process.env.NODE_ENV === 'development') {
const { default: DevTools } = await import('./DevTools');
return DevTools;
}
return null;
};
性能优化配置示例
javascript
const path = require('path');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
mode: 'production',
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename]
}
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
terserOptions: {
compress: {
drop_console: true
}
}
})
],
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10
}
}
},
runtimeChunk: 'single',
moduleIds: 'deterministic',
chunkIds: 'deterministic'
},
resolve: {
modules: [
path.resolve(__dirname, 'src'),
'node_modules'
],
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components')
}
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
],
performance: {
maxAssetSize: 250000,
maxEntrypointSize: 250000,
hints: 'warning'
}
};
小结
Webpack 性能优化是一个持续的过程,需要根据项目特点和需求进行调整。关键优化点包括缓存配置、模块解析优化、代码分割、Tree Shaking、资源优化等。通过合理的配置和优化策略,可以显著提升构建速度和输出质量。