

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=gbsa5hpojof
splitChunks/runtimeChunk)、持久化缓存(cache: filesystem)、并行压缩与 loader 缓存、增量构建与 SourceMap 优化webpack --profile --json > stats.json + webpack-bundle-analyzer;speed-measure-webpack-plugin 分析时间占比webpack.config.js
const path = require('path')
const TerserPlugin = require('terser-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer')
module.exports = {
mode: process.env.NODE_ENV || 'production',
entry: { app: './src/index.tsx' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash:8].js',
chunkFilename: 'js/[name].[contenthash:8].js',
assetModuleFilename: 'assets/[name].[hash][ext]'
},
devtool: process.env.NODE_ENV === 'production' ? 'source-map' : 'cheap-module-source-map',
resolve: { extensions: ['.ts', '.tsx', '.js', '.json'] },
cache: {
type: 'filesystem',
allowCollectingMemory: true,
cacheDirectory: path.resolve(__dirname, '.cache/webpack'),
buildDependencies: { config: [__filename] }
},
optimization: {
splitChunks: {
chunks: 'all',
minSize: 20 * 1024,
cacheGroups: {
vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendor', priority: 10, reuseExistingChunk: true },
ui: { test: /(element-plus|antd|@mui)/, name: 'ui', priority: 9 },
commons: { name: 'commons', minChunks: 2, priority: 1 }
}
},
runtimeChunk: 'single',
moduleIds: 'deterministic',
minimizer: [
new TerserPlugin({ parallel: true, extractComments: false, terserOptions: { format: { comments: false } } }),
new CssMinimizerPlugin()
]
},
module: {
rules: [
{ test: /\.(png|jpg|jpeg|gif|svg)$/i, type: 'asset', parser: { dataUrlCondition: { maxSize: 10 * 1024 } } },
{ test: /\.(woff2?|ttf|eot)$/, type: 'asset/resource' },
{
test: /\.(ts|tsx|js)$/,
use: [
{ loader: 'thread-loader', options: { workers: Math.max(1, require('os').cpus().length - 1) } },
{ loader: 'babel-loader', options: { cacheDirectory: true } }
],
exclude: /node_modules/
},
{
test: /\.css$/,
use: [ 'style-loader', { loader: 'css-loader', options: { sourceMap: true } } ]
}
]
},
plugins: [
// 按需启用分析
process.env.ANALYZE ? new BundleAnalyzerPlugin({ analyzerMode: 'static' }) : null
].filter(Boolean)
}splitChunks.chunks: 'all':统一管理同步/异步资源,避免重复打包cacheGroups.vendor/ui/commons:框架与重 UI 库独立分包、公共代码抽取,提升缓存命中率runtimeChunk: 'single':独立运行时代码以避免因 manifest 变化导致大包失效moduleIds: 'deterministic':稳定 chunk 与 module id,减少二次构建与缓存失效高级策略:
maxAsyncRequests/maxInitialRequests 控制并发请求上限(避免首屏碎片过多):optimization: { splitChunks: { maxInitialRequests: 10, maxAsyncRequests: 20 } }enforceSizeThreshold 避免极小碎片:optimization: { splitChunks: { enforceSizeThreshold: 50 * 1024 } }name 或 cacheGroups 合并,减少并发请求cache: filesystem 显著缩短二次构建;存放 .cache/webpack 并在 CI 缓存目录babel-loader 开启 cacheDirectory;thread-loader 并行转译ts-loader 可使用 transpileOnly + fork-ts-checker-webpack-plugin 分离类型检查(或改用 babel + ts 仅转译)快照与不可变路径(减少文件系统扫描):
snapshot: {
managedPaths: [/^(.+)?node_modules/],
immutablePaths: [/^(.+)?node_modules/]
}实验特性(根据项目启用):
experiments: { cacheUnaffected: true, lazyCompilation: true }说明:cacheUnaffected 跳过未受影响模块的重新计算;lazyCompilation 对 import() 进行按需编译,提升开发体验。
TerserPlugin 并行压缩;生产 source-map,开发 cheap-module-source-mapCssMinimizerPlugin 压缩;避免过重的 inline-source-mapdevtool 有层级,避免在开发环境生成全量映射导致变慢替代方案(更快编译):
// 使用 esbuild 代替 Terser
const EsbuildPlugin = require('esbuild-loader').EsbuildPlugin
optimization: { minimizer: [ new EsbuildPlugin({ target: 'es2017' }) ] }
// 使用 swc/esbuild-loader 代替 babel-loader
{
test: /\.(ts|tsx|js)$/,
loader: 'esbuild-loader',
options: { loader: 'tsx', target: 'es2017' },
exclude: /node_modules/
}asset/asset-resource/asset-inline 替代 file-loader/url-loader,统一资源处理image-minimizer-webpack-plugin(可选)与现代格式(WebP/AVIF)图片压缩示例:
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin')
optimization: {
minimizer: [
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: { plugins: [ ['mozjpeg', { quality: 75 }], ['pngquant', { quality: [0.65, 0.8] }], ['svgo', {}] ] }
}
})
]
}长效缓存与 CDN:
output: { publicPath: 'https://cdn.example.com/', clean: true }thread-loader:为耗时 loader(如 babel/ts)并行处理TerserPlugin.parallel: true:压缩并行;配置 keep_fnames: false 减小体积cache: filesystem + 轻量 SourceMap;HotModuleReplacement 减少全量刷新.cache/webpack 与 node_modules;增量依赖安装(pnpm/npm ci)DevServer 示例:
devServer: {
static: { directory: path.join(__dirname, 'public') },
compress: true,
hot: true,
client: { overlay: true },
headers: { 'Cache-Control': 'public, max-age=0' }
}CI(GitHub Actions)缓存示例:
- uses: actions/cache@v3
with:
path: |
~/.npm
./.cache/webpack
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-webpack-${{ hashFiles('**/webpack.config.js') }}speed-measure-webpack-plugin、webpack-bundle-analyzer、CI 构建日志采集Profiling:
NODE_OPTIONS="--trace-deopt --trace_gc" webpack --profile --json > stats.json结合 stats.json 与分析工具定位热路径与耗时 loader。
runtimeChunk 与 deterministic id;避免每次构建修改 chunk 内容thread-loader workers更多提示:
hard-source-webpack-plugin(已过时)与 Webpack5 内置缓存resolve.symlinks: false 可减少工作区/monorepo 的模块解析开销(按需)