前言
rspack作为字节撼动前端构建界的一大利器,业界缺少实际项目的支撑经验。本着优化项目第一,锻炼技术第二的目的,我就这样出发了。
rspack 由rust开发,如果说vite将速度从自行车推到了摩托车时代,那么rust将前端构建从摩托车到了飞行器体验的时代,无论是vue旧版本还是react新版本,都将由rspack至快的速度来驱动。
下面就我几个项目的优化和升级的经验分享一下,本着个人经验不具备普遍的前提原则下,还望大家轻拍。
1. 项目背景
-
项目类型:xx后台管理系统
-
技术栈:Vue 2.5 + Element UI
-
项目规模:
-
代码量:约 23w+ 行
-
页面数:200+ 个业务页面
-
基于 vue-element-admin(Webpack3 分支)模板开发
-
-
设备:MacBook Pro M1 Pro 32GB
1.2 现存问题
-
开发效率低下
-
首次加载时间:41.1 秒
-
打包时间:55.48 秒
-
热更新时间:4.01 秒
-
每次操作都需要等待将近 1 分钟
-
-
已尝试的优化方案
-
添加缓存优化
-
优化 loader 配置
-
调整 Webpack 配置
-
但效果均不明显,仍然存在性能瓶颈。
2. 方案调研
2.1 可选方案对比
方案 | 优势 | 劣势 | 迁移成本 |
---|---|---|---|
Webpack 5 | 生态成熟,稳定性高,广泛的社区支持 | 配置复杂,构建速度较慢,性能瓶颈 | 低 |
Vite | 开发体验极佳,启动和热更新快,配置简洁 | 生产构建慢,插件生态不完善 | 高 |
Rspack | 性能优越,兼容 Webpack 生态,资源消耗少 | 相对较新,部分功能待完善 | 低 |
2.2 选择 Rspack 的原因
-
性能优势
-
与 Webpack 相比有显著提升
-
接近 Vite 的开发体验
-
基于Rust开发
-
-
迁移成本低
-
兼容大部分 Webpack 配置
-
支持渐进式迁移
-
-
生态兼容
-
复用现有 Webpack 生态
-
支持主流 loader 和 plugin
-
3. 迁移实施
3.1 环境准备
- Node 版本升级
{
"volta": {
"node": "20.10.0", // 从 14.16.0 升级
"yarn": "1.22.5"
}
}
- 安装核心依赖
npm i @rspack/cli @rspack/core -D
npm i vue-loader@15.11.1 vue-style-loader@4.1.3 babel-loader @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props -D
3.2 核心配置改造
- 基础配置
const path = require('path');
const { defineConfig } = require('@rspack/cli');
module.exports = defineConfig({
entry: {
main: "./src/main.js"
},
devtool: process.env.NODE_ENV === 'development' ? 'eval' : false,
resolve: {
alias: {
"@": path.resolve(__dirname, 'src'),
vue$: 'vue/dist/vue.esm.js',
'@remote-common': path.resolve('remote-common')
},
extensions: [".js", ".json", ".wasm", '.vue', '.jsx', '.tsx'],
modules: [
path.resolve(__dirname, 'src'),
'node_modules'
],
}
})
- Vue 相关配置
module.exports = defineConfig({
plugins: [
new VueLoaderPlugin(),
],
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: "vue-loader",
options: {
experimentalInlineMatchResource: true
}
}
]
},
{
test: /\.[jt]sx$/,
use: {
loader: "babel-loader",
options: {
presets: [
["@vue/babel-preset-jsx", { compositionAPI: true }]
]
}
},
}
]
}
})
- 样式处理
module.exports = defineConfig({
module: {
rules: [
{
test: /\.less$/,
loader: "less-loader",
type: "css",
},
{
test: /\.scss$/,
loader: "sass-loader",
type: "css",
exclude: /node_modules/,
}
]
}
})
- 静态资源处理
module.exports = defineConfig({
module: {
rules: [
{
test: /\.svg$/,
include: [path.join(__dirname, 'src/icons/svg')],
use: [
{
loader: 'svg-sprite-loader',
options: {
symbolId: 'icon-[name]'
}
}
]
},
{
test: /\.(png|jpg|jpeg|gif|webp)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024,
},
},
generator: {
filename: 'images/[hash][ext]',
},
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 4 * 1024,
},
},
generator: {
filename: 'fonts/[hash][ext]'
}
}
]
}
})
3.3 环境变量配置
const dotenv = require('dotenv');
const DotenvWebpack = require('dotenv-webpack');
module.exports = defineConfig({
plugins: [
new DotenvWebpack({
path: `.env.${process.env.NODE_ENV}`,
safe: false,
allowEmptyValues: true,
systemvars: true,
silent: false,
defaults: false,
})
],
optimization: {
minimize: !isDev,
nodeEnv: false, // 这很重要,可以自定义 .env.[mode]
moduleIds: 'deterministic',
splitChunks: !isDev ? {
chunks: 'all',
minSize: 200000,
maxSize: 0,
cacheGroups: {
styles: {
name: 'styles',
type: 'css/mini-extract',
chunks: 'all',
enforce: true,
},
},
} : false,
}
})
4. 性能对比
4.1 详细指标对比
指标 | Webpack | Rspack | 提升比例 |
---|---|---|---|
首次加载 | 41.1s | 13.43s | -67.3% |
二次加载 | 40.11s | 12.11s | -69.8% |
构建时间 | 55.48s | 7.69s | -86.1% |
热更新 | 4.01s | 1.45s | -63.8% |
4.2 构建产物对比
-
总体积减少约 15%
-
chunk 分割更合理
-
GZIP 压缩后体积进一步优化
5. 遇到的问题与解决方案
- rspack 启动依赖报错
[rspack-cli] Error: Cannot find module 'webpack/lib/rules/BasicEffectRulePlugin'
解决方案:手动再添加webpack5 相关issues
- sass-loader 警告
module.exports = defineConfig({
ignoreWarnings: [
(warning) => warning.message.includes('sass-loader')
],
})
5.2 静态资源处理
- 图片加载问题
-
使用 asset 模块替代 url-loader
-
调整资源大小阈值
- 字体文件处理
-
统一使用 asset 类型处理
-
配置合适的输出路径
6. 经验总结
6.1 迁移建议
-
循序渐进
-
先进行基础配置迁移
-
逐步替换 loader 和 plugin
-
保持功能的完整性验证
-
-
版本选择
-
选择稳定版本
-
关注官方更新动态
-
及时跟进 bug 修复
-
6.2 注意事项
-
兼容性处理
-
检查第三方依赖兼容性
-
保留必要的 polyfill
-
注意浏览器支持范围
-
-
性能优化
-
合理配置 splitChunks
-
启用 GZIP 压缩
-
使用 RsDoctor 进行性能分析
-
6.3 后续计划
-
持续优化
-
进一步优化构建配置
-
探索更多性能提升空间
-
跟进 Rspack 新特性
-
-
监控完善
-
添加构建性能监控
-
完善错误收集机制
-
建立性能基准数据
-
总结
从实践效果来看,Rspack 确实为项目带来了显著的性能提升,特别是在开发体验和构建速度方面。虽然 Rspack 仍在快速发展中,但其兼容 Webpack 生态的特性使得迁移成本相对可控。随着 Rspack 的不断完善,相信未来会带来更多的性能优化和功能改进。
这次迁移不仅提升了团队的开发效率,也为后续的项目优化提供了新的思路和可能性。建议有类似需求的团队可以考虑尝试 Rspack,但要注意评估项目的具体情况和可能遇到的风险。