在前端项目上线前,「构建优化」是绕不开的环节 ------ 既要保证代码压缩到最小体积(提升加载速度),又要通过代码分割减少重复代码(降低缓存失效成本)。
Rspack 作为下一代打包工具,内置了两套核心优化工具:SwcJsMinimizerRspackPlugin
(基于 Rust 的 JS 压缩器,速度远超 Terser)和 LightningCssMinimizerRspackPlugin
(高性能 CSS 压缩器),再配合 splitChunks
代码分割,能轻松实现 "快构建 + 小体积"。本文就带你逐行拆解这套优化配置,学完直接复用。
一、先理清优化核心:这 3 个配置解决什么问题?
在看具体代码前,先明确优化目标 ------ 避免 "为了优化而优化",每一项配置都要对应实际问题:
- JS 压缩 :用
SwcJsMinimizerRspackPlugin
替代传统 Terser,在压缩 JS 时移除无用代码、console/debugger,同时兼容 ES5(支持旧浏览器); - CSS 压缩 :用
LightningCssMinimizerRspackPlugin
压缩 CSS,自动处理前缀兼容,比 cssnano 更快; - 代码分割 :用
splitChunks
将第三方库(如 Vue/React)、公共代码拆分成独立 chunk,实现 "一次加载、多次复用",减少重复加载体积。
二、核心配置拆解:从 JS 压缩到代码分割
第一步:全局优化开关 optimization
整个优化逻辑都在 optimization
配置项中,先看整体结构,再逐模块拆解:
java
// rspack.config.js
const rspack = require('@rspack/core'); // 引入 Rspack 核心
module.exports = {
// 其他基础配置(入口、出口、loader 等)...
optimization: {
// 1. 全局开启压缩(生产环境必须设为 true,开发环境建议 false 提速)
minimize: true,
// 2. 配置具体的压缩器(JS + CSS)
minimizer: [/* 下文详细拆解 */],
// 3. 代码分割规则(拆分第三方库、公共代码)
splitChunks: {/* 下文详细拆解 */},
// 4. 提取 runtime 代码(避免缓存失效问题)
runtimeChunk: { name: 'runtime' }
}
};
⚠️ 注意:
minimize: true
仅建议在生产环境开启!开发环境开启压缩会大幅拖慢构建速度,且不利于调试(代码被混淆)。
第二步:JS 压缩配置 SwcJsMinimizerRspackPlugin
这是 Rspack 内置的 JS 压缩插件,基于 SWC(Rust 编写),压缩速度是 Terser 的 5-10 倍,同时支持精细化配置(如保留关键变量、移除 console 等):
javascript
// 接上面的 optimization.minimizer
minimizer: [
// 1. JS 压缩器:SwcJsMinimizerRspackPlugin
new rspack.SwcJsMinimizerRspackPlugin({
// 规则:不压缩 .xlsx 相关的 JS 文件(按需配置,比如 xlsx 库压缩后可能报错)
test: /^(?!.*xlsx).*\.js$/,
// JS 压缩的核心配置
minimizerOptions: {
// jsc:控制 JS 语法处理
jsc: {
// 输出 ES5 兼容代码(关键!支持 IE 11 等旧浏览器,避免箭头函数、let 等语法报错)
target: 'es5'
},
// compress:代码压缩优化(最核心的体积优化项)
compress: {
drop_console: true, // 移除所有 console 语句(线上无需调试日志)
drop_debugger: true, // 移除 debugger 语句(避免线上调试入口)
passes: 2, // 压缩次数:2 次(比默认 1 次压缩更彻底,体积更小)
keep_infinity: true, // 保留 Infinity(避免压缩后变成 1/0,部分场景报错)
comparisons: false, // 禁用比较优化(如 a <= b 不转成 a < b || a === b,兼容旧浏览器)
pure_funcs: [], // 标记"无副作用"的函数(如 lodash 的 noop,可安全移除)
// --- 强力推荐配置:进一步减小体积 ---
unused: true, // 移除未使用的变量/函数(比如定义了但没调用的函数)
dead_code: true, // 移除死代码(比如 if(false) 里的代码)
evaluate: true, // 编译时计算常量(比如 1+2 直接转成 3)
join_vars: true, // 合并 var 声明(比如 var a=1;var b=2 → var a=1,b=2)
properties: true, // 优化属性访问(比如 obj['name'] → obj.name)
side_effects: true // 移除无副作用的代码(比如单独的 var a=3; 且没被使用)
},
// mangle:变量名混淆(减小体积,但需保留关键变量避免报错)
mangle: {
// 保留不被混淆的变量名(比如 Vue 的 _c/_v 等渲染函数,混淆后会报错)
reserved: ['$', 'exports', 'require', '_c', '_v', '_s', '_e'],
keep_fnames: false // 不保留函数名(true 则保留,体积会大一点,但便于调试)
},
// format:输出格式控制
format: {
comments: false, // 移除所有注释(注释不影响运行,纯占体积)
ascii_only: true // 强制输出 ASCII 字符(避免中文等非 ASCII 字符转义后体积变大)
}
}
}),
// 2. CSS 压缩器:LightningCssMinimizerRspackPlugin(下文拆解)
new rspack.LightningCssMinimizerRspackPlugin({/* ... */})
]
关键配置避坑(线上报错高频点):
-
test: /^(?!.*xlsx).*\.js$/
:必须排除特殊库(如 xlsx、pdfjs)!这类库的源码可能包含特殊语法,压缩后会导致功能失效(比如 xlsx 的二进制处理逻辑被破坏),需要根据项目依赖调整排除规则。
-
mangle.reserved
:一定要保留框架 / 库的关键变量!比如 Vue 的
_c
(创建元素)、_v
(创建文本节点),React 的React
等,混淆后会导致渲染报错 ------ 如果用了其他框架,需追加对应变量名。 -
jsc.target: 'es5'
:若项目需要支持 IE 11,必须设为
es5
;若只支持现代浏览器(Chrome 60+、Safari 14+),可设为es2015
,压缩后体积更小(无需转译箭头函数、let 等)。
第三步:CSS 压缩配置 LightningCssMinimizerRspackPlugin
这是 Rspack 推荐的 CSS 压缩器,基于 Lightning CSS(Rust 编写),比传统的 css-minimizer-webpack-plugin
快 10 倍以上,还能自动处理浏览器前缀:
php
// 接上面的 minimizer 数组
new rspack.LightningCssMinimizerRspackPlugin({
minimizerOptions: {
// 兼容目标:defaults(自动读取 .browserslistrc 配置,无需重复写 targets)
targets: 'defaults'
}
})
配置解读:
-
targets: 'defaults'
:无需手动写浏览器兼容列表!Lightning CSS 会自动读取项目根目录的
.browserslistrc
(比如之前配置的ie >= 11
、> 1%
),自动添加所需的 CSS 前缀(如-ms-
、-webkit-
),避免重复配置。 -
额外优化(可选) :
若需要更精细控制(如移除 unused CSS),可添加
drafts: { unusedSymbols: true }
,但需注意:移除 unused CSS 可能误删动态使用的样式(如document.styleSheets
操作的样式),需测试后启用:minimizerOptions: { targets: 'defaults', drafts: { unusedSymbols: true } // 移除未使用的 CSS 选择器(谨慎启用) }
第四步:代码分割 splitChunks + runtimeChunk
代码分割是 "减少重复加载" 的核心 ------ 把第三方库、公共代码拆分成独立 chunk,用户首次加载后,后续页面可复用缓存,无需重复下载:
javascript
// 接上面的 optimization
splitChunks: {
chunks: 'all', // 分割所有类型的 chunk(initial 初始 chunk、async 异步 chunk)
maxSize: 244 * 1024, // 单个 chunk 最大体积:244KB(超过则自动拆分,避免单个文件过大)
minSize: 30 * 1024, // 单个 chunk 最小体积:30KB(小于则不拆分,避免太多小文件)
// 缓存组:按规则拆分不同类型的代码
cacheGroups: {
// 1. 第三方库缓存组(node_modules 里的代码)
vendors: {
test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 目录下的文件
name: 'chunk-vendors', // 拆分后的 chunk 名:chunk-vendors.js
priority: -10, // 优先级:-10(比 common 高,先匹配 vendors)
chunks: 'all' // 分割所有类型的 chunks
},
// 2. 公共代码缓存组(项目内被多次引用的代码)
common: {
name: 'chunk-common', // 拆分后的 chunk 名:chunk-common.js
minChunks: 2, // 最小引用次数:2 次(被 2 个及以上文件引用才拆分)
priority: -20, // 优先级:-20(低于 vendors,避免公共代码被归为 vendors)
reuseExistingChunk: true, // 复用已存在的 chunk(比如 A 引用 B,B 已拆分成 chunk,则 A 直接复用)
chunks: 'all'
}
}
},
// 提取 runtime 代码(关键!避免缓存失效)
runtimeChunk: {
name: 'runtime' // 把 webpack/rspack 的运行时代码(如模块映射关系)拆成独立 chunk
}
代码分割核心逻辑(为什么要这么拆):
-
chunk-vendors
:第三方库(如 Vue、lodash、axios)更新频率低,拆成独立 chunk 后,用户首次加载后会缓存,后续项目业务代码更新时,
chunk-vendors
不会重新下载,减少加载体积。 -
chunk-common
:项目内的公共代码(如 utils 工具函数、公共组件)被多次引用,拆分成独立 chunk 后,避免在多个业务 chunk 中重复打包,减少整体体积。
-
runtime
chunk :运行时代码包含 "模块映射关系"(比如哪个模块对应哪个文件),如果不提取,每次业务代码更新时,运行时代码也会跟着变,导致
chunk-vendors
等缓存失效 ------ 提取后,runtime
体积很小(几十 KB),且只有当模块映射关系变化时才会更新。
三、验证优化效果:3 个维度检查
配置完成后,执行生产构建命令(pnpm run build
),通过以下 3 个维度验证优化是否生效:
1. 查看产物体积变化
对比优化前后的 dist
目录总大小:
- JS 压缩:通常能减少 30%-50% 体积(比如 1MB 的 JS 压缩后变成 500KB 左右);
- CSS 压缩:通常能减少 20%-40% 体积(比如 200KB 的 CSS 压缩后变成 120KB 左右);
- 代码分割:拆分出
chunk-vendors.js
、chunk-common.js
、runtime.js
,且单个 chunk 体积不超过 244KB(符合maxSize
配置)。
2. 检查 JS 压缩效果
打开 dist/js
目录下的压缩文件,确认:
- 无
console.log
、debugger
语句(drop_console
/drop_debugger
生效); - 变量名被混淆(如
userName
变成a
,但$
、_c
等保留变量未被混淆); - 无注释(
format.comments: false
生效)。
3. 检查 CSS 压缩效果
打开 dist/css
目录下的压缩文件,确认:
- 空格、换行被移除(压缩生效);
- 自动添加了浏览器前缀(如
-ms-flex
、-webkit-box
,对应.browserslistrc
配置); - 无未使用的 CSS 选择器(若启用了
unusedSymbols
)。
四、进阶优化建议:根据项目调整
1. 异步 chunk 优化
如果项目用了动态导入(import('xxx')
),可在 splitChunks
中添加异步 chunk 专属配置,进一步拆分:
javascript
splitChunks: {
// 原有配置...
cacheGroups: {
// 原有配置...
// 新增:异步 chunk 缓存组(比如路由组件)
async: {
name: 'chunk-async',
test: /[\\/]src[\\/]views[\\/]/, // 匹配路由视图组件
minChunks: 1,
priority: -15,
chunks: 'async' // 只处理异步 chunk
}
}
}
2. 控制 chunk-vendors 体积
如果 chunk-vendors
体积过大(比如超过 1MB),可拆分大型第三方库(如 xlsx、echarts):
javascript
splitChunks: {
// 原有配置...
cacheGroups: {
vendors: {
// 原有配置...
// 拆分大型库:把 xlsx 单独拆成 chunk
test: [/[\\/]node_modules[\\/]/, /[\\/]node_modules[\\/]xlsx[\\/]/],
name(module) {
// 对 xlsx 单独命名,其他第三方库归为 chunk-vendors
const match = module.resource.match(/[\\/]node_modules[\\/](xlsx)[\\/]/);
return match ? `chunk-${match[1]}` : 'chunk-vendors';
}
}
}
}
3. 开发环境关闭优化
在 rspack.config.js
中根据环境动态控制 minimize
,避免开发环境变慢:
arduino
optimization: {
// 开发环境关闭压缩,生产环境开启
minimize: process.env.NODE_ENV === 'production',
// 其他配置...
}
总结
Rspack 的优化配置核心是「用 Rust 工具提速 」和「精细化拆分代码」,这套配置可直接复用,关键总结为 3 点:
- JS 压缩:用
SwcJsMinimizerRspackPlugin
,重点配置compress
移除无用代码、mangle
保留关键变量、jsc.target
保证兼容; - CSS 压缩:用
LightningCssMinimizerRspackPlugin
,依赖.browserslistrc
自动兼容,无需重复配置; - 代码分割:用
splitChunks
拆分第三方库和公共代码,用runtimeChunk
保护缓存,避免失效。
相比 Webpack 传统优化方案,这套配置的构建速度能提升 5-10 倍,产物体积能减少 30%-50%,且无需额外安装大量依赖(Rspack 内置核心插件)。
你在 Rspack 优化中还遇到过哪些问题?比如大型库拆分、异步 chunk 体积控制等,欢迎在评论区分享你的解决方案~