Webpack 构建速度优化
Webpack 构建速度优化是一个系统工程,需要从多个维度进行优化。以下是全面的优化方案:
1. 分析工具先行
1.1 构建速度分析
# 安装速度分析插件
npm install --save-dev speed-measure-webpack-plugin
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()
module.exports = smp.wrap({
// webpack 配置
plugins: [
// ... 其他插件
]
})
1.2 打包体积分析
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: 'server',
openAnalyzer: true
})
]
}
1.3 构建过程分析
const { ProgressPlugin } = require('webpack')
module.exports = {
plugins: [
new ProgressPlugin({
activeModules: true, // 显示活跃模块
entries: true, // 显示入口
modules: true, // 显示模块
dependencies: true, // 显示依赖
})
]
}
2. 优化解析和编译
2.1 缩小文件搜索范围
module.exports = {
resolve: {
// 明确第三方模块路径
modules: [path.resolve(__dirname, 'node_modules')],
// 减少后缀尝试
extensions: ['.ts', '.tsx', '.js', '.jsx'],
// 使用别名避免层层查找
alias: {
'@': path.resolve(__dirname, 'src'),
'react': path.resolve(__dirname, './node_modules/react'),
}
},
module: {
rules: [
{
test: /\.js$/,
// 只处理 src 目录下的文件
include: path.resolve(__dirname, 'src'),
use: ['babel-loader']
}
]
}
}
2.2 避免不必要的解析
module.exports = {
module: {
// 不解析已知的预编译库
noParse: /jquery|lodash|moment/,
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true, // 开启 babel 缓存
cacheCompression: false // 关闭缓存压缩
}
}
}
]
}
}
3. 利用缓存机制
3.1 Webpack 5 持久化缓存
module.exports = {
cache: {
type: 'filesystem', // 使用文件系统缓存
buildDependencies: {
config: [__filename] // 构建依赖配置
},
cacheDirectory: path.resolve(__dirname, 'node_modules/.cache/webpack')
}
}
3.2 Webpack 4 缓存方案
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
module.exports = {
plugins: [
new HardSourceWebpackPlugin(),
// 或者使用 cache-loader
],
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'cache-loader',
options: {
cacheDirectory: path.resolve('.cache')
}
},
'babel-loader'
]
}
]
}
}
4. 多进程/多实例构建
4.1 Thread Loader (推荐)
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'thread-loader',
options: {
workers: require('os').cpus().length - 1, // CPU 核心数 - 1
poolTimeout: Infinity // 开发模式保持进程运行
}
},
'babel-loader'
]
}
]
}
}
4.2 Terser 多进程压缩
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true, // 开启多进程
terserOptions: {
compress: {
drop_console: true // 生产环境移除 console
}
}
})
]
}
}
5. 代码分割与按需加载
5.1 动态导入
// 路由懒加载
const Home = () => import(/* webpackChunkName: "home" */ './views/Home.vue')
const About = () => import(/* webpackChunkName: "about" */ './views/About.vue')
// 组件懒加载
const HeavyComponent = () => import('./components/HeavyComponent.vue')
5.2 SplitChunks 优化
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
chunks: 'all'
},
common: {
name: 'common',
minChunks: 2,
priority: 5,
reuseExistingChunk: true
}
}
}
}
}
6. DLL 预编译(适用于大型项目)
6.1 创建 DLL 配置
// webpack.dll.config.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
mode: 'production',
entry: {
vendor: ['react', 'react-dom', 'lodash', 'moment']
},
output: {
path: path.resolve(__dirname, 'dll'),
filename: '[name].dll.js',
library: '[name]_library'
},
plugins: [
new webpack.DllPlugin({
name: '[name]_library',
path: path.join(__dirname, 'dll', '[name]-manifest.json')
})
]
}
6.2 使用 DLL
// webpack.config.js
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.DllReferencePlugin({
manifest: require('./dll/vendor-manifest.json')
})
]
}
7. 开发环境优化
7.1 增量编译
module.exports = {
watch: true,
watchOptions: {
ignored: /node_modules/, // 忽略 node_modules
aggregateTimeout: 300, // 防抖延迟
poll: 1000 // 轮询间隔
}
}
7.2 热更新优化
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')
module.exports = {
devServer: {
hot: true,
port: 8080,
compress: true, // 开启 gzip
overlay: true, // 显示错误覆盖层
stats: 'minimal' // 减少控制台输出
},
plugins: [
new ReactRefreshWebpackPlugin() // React 热更新
]
}
8. 生产环境优化
8.1 资源压缩
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
optimization: {
minimize: true,
minimizer: [
new TerserPlugin(), // JS 压缩
new CssMinimizerPlugin() // CSS 压缩
]
},
plugins: [
new CompressionPlugin({ // Gzip 压缩
test: /\.(js|css|html|svg)$/,
threshold: 8192
})
]
}
8.2 预编译资源
const PrepackWebpackPlugin = require('prepack-webpack-plugin').default
module.exports = {
plugins: [
// 预编译常量
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
// 预编译资源(可选)
new PrepackWebpackPlugin()
]
}
9. 高级优化技巧
9.1 模块联邦 (Webpack 5)
// app1 webpack.config.js
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/Button'
},
shared: ['react', 'react-dom']
})
]
}
9.2 资源内联
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 8KB 以下转 base64
fallback: 'file-loader'
}
}
]
}
]
}
}
10. 监控与持续优化
10.1 构建监控
// 构建耗时监控
class BuildTimePlugin {
apply(compiler) {
let startTime
compiler.hooks.beforeRun.tap('BuildTimePlugin', () => {
startTime = Date.now()
})
compiler.hooks.done.tap('BuildTimePlugin', () => {
const endTime = Date.now()
console.log(`构建耗时: ${(endTime - startTime) / 1000}秒`)
})
}
}
10.2 配置文件优化建议
// 根据环境使用不同配置
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production'
return {
mode: argv.mode || 'development',
devtool: isProduction ? 'source-map' : 'eval-cheap-module-source-map',
// 其他配置...
}
}
优化效果评估
实施这些优化后,通常可以看到:
- 开发环境:冷启动时间减少 50-70%,热更新时间减少 60-80%
- 生产环境:构建时间减少 30-50%,打包体积减少 20-40%
建议根据项目实际情况选择适合的优化方案,优先解决性能瓶颈最严重的环节。
挣钱养家

浙公网安备 33010602011771号