看了这篇《开发体验的彻底提升,从 Vite 迁移到 Rspack》,作者提到Rsbuild(Rspack对标Webpack,Rsbuild进一步封装,提供大量开箱即用的功能,体验类似于Vite),相比于Vite的优势:
Rspack解决了页面加载速度瓶颈问题,其构建机制不会导致页面请求数过多;- 开发环境与生产环境一致(
Vite将来使用Rolldown可解决); - 打包速度惊人,项目打包速度提升 80% 以上,使开发流程更流畅。
有些心动。
于是,我决定尝试把现有项目改造成 rsbuild,看下到底有多大的提升。
这是一个rsbuild(v1.0.4)的配置文件,用到了ElementPlus免引入,https、sass,所以配置麻烦一些:
import { fileURLToPath, URL } from 'node:url';
import { pluginVue } from '@rsbuild/plugin-vue';
import { pluginVueJsx } from '@rsbuild/plugin-vue-jsx';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import Components from 'unplugin-vue-components/rspack';
import AutoImport from 'unplugin-auto-import/rspack';
import { pluginBasicSsl } from '@rsbuild/plugin-basic-ssl';
import { pluginSass } from '@rsbuild/plugin-sass';
export default {
html: {
template: 'public/index.html'
},
source: {
entry: {
index: './src/main.ts'
},
define: {
'process.env.BASE_URL': '"/"'
},
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
port: 443,
host: '0.0.0.0',
proxy: {
'/api': {
target: "https://xx.xxx.com",
changeOrigin: true,
},
'/pan-api': {
target: "https://pan.xxx.cn",
changeOrigin: true,
pathRewrite: {
'^/pan-api': '/api',
},
}
}
},
plugins: [pluginVue(), pluginVueJsx(), pluginSass(), pluginBasicSsl()],
tools: {
rspack: {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver({})]
}),
Components({
resolvers: [ElementPlusResolver({})]
})
]
}
}
};
整体风格语法看起来与Vite比较类似,大家可以先去这里找下插件,遇到Rsbuild没有的插件,再找Rspack有没有,大部分常用的插件都有了。
构建对比
我们看下GitLab流水线构建步骤的变化。
工程A,改造前用的Webpack,用时7分55秒:
使用swc-loader后相差不多:
而改造为rsbuild后是44秒:
炸裂。
当然,流水线的机器CPU分配很低,没有进行调优。
本地开发(M1 Pro)更快,改造前构建是36秒,改造后是4秒,大概是9倍的差距,吊打Webpack确实没商量。
再看工程B,Vite项目(v5.0.11),改造起来要简单多了。改造前是3分08秒:
改造后是45秒:
大概是3倍+的差距。
本地构建(M1 Pro)不是很明显,改造前是8秒7,改造后是4秒5。这可能与项目体量不大有关。
开发体验
与Webpack相比,Rsbuild有Rust的加持,完全是碾压的优势,全方位降维打击。
开发体验上,原来Webpack dev启动弹出了页面,但要过差不多15秒才能看到页面,而改造后与Vite体验一样,秒开,太丝滑了。
这个我并不意外。
有些意外的是,我的Vite项目,一个后台管理页面,在开发阶段消除了我一个困扰多时的问题。
改造前某个路由里有159个JS请求:
改造后只在16个JS了:
项目没到作者的体量,所以页面加载时间上二者差距不是很大。我说的意外是,项目里用到了ElementPlus,使用unplugin-vue-components动态注入的import,导致一个严重的问题是切换路由时可能会触发页面重新加载:
15:17:23 [vite] ✨ new dependencies optimized: element-plus/es/components/form/style/css, element-plus/es/components/text/style/css, element-plus/es/components/form-item/style/css
15:17:23 [vite] ✨ optimized dependencies changed. reloading
从打印信息上看,是因为使用了路由懒加载,临时检测到有动态的ElementPlus组件使用,需要重新处理依赖关系,就刷新了,这在开发过程中非体验很不友好。
使用Rsbuild改造后,解决了。仔细一想,意料之外,情理之中。
这里贴一张原文描述Rsbuild与Vite随着源文件数量的增加页面重载速度曲线图:
改造细节
大部分情况下,只需要进行配置文件的修改,按照官方的迁移指南进行就可以了。
Vite项目里,有段代码用到了import.meta.glob:
const modules: Record<string, any> = import.meta.glob(['./modules/**/*.ts'], {
eager: true
});
Object.keys(modules).forEach((key) => {
const module = modules[key].default as RouteConfig;
routes.push(module);
});
这是 Vite专有的API,不是标准里的,rsbuild团队成员回应在考虑要不要实现它:
这个API很奇葩,按理说它是个Node.js层面的东西,偏偏出现在前端,目的就是为了可以自动引入代码。要么怎么说前端太卷呢,什么样的轮子都有。
我要做测试,这段代码得修改,怎么改呢,其实也简单,按照这段示例修改为Rspack支持的import.meta.webpackContext就可以了:
const modules = import.meta.webpackContext('./modules', {
recursive: false
});
for (const path of modules.keys()) {
const module = modules(path).default as RouteConfig;
routes.push(module);
}
当然,如果不使用这两个与构建工具强关联的函数,可以考虑在modules里写一个index.ts,把这些文件都导出来(这种代码当然是Copilot帮忙写的):
export { default as app } from './app';
export { default as auth } from './auth';
export { default as cdn } from './cdn';
...
再修改原代码:
import * as modules from './modules';
Object.keys(modules).forEach((key) => {
const module = modules[key];
routes.push(module);
});
也不是很麻烦。
总结
我将两个项目改造为Rsbuild。
- 在
GitLab流水线的构建环节上,相比于Webpack有9倍的差距,相比于Vite有3倍的差距。 - 在开发阶段,与
Vite类似同样做到了秒开,且由于加载机制的不同,在源码文件巨多时会有更大体验优势。我的项目中用到动态注入ElementPlus的引用,在Vite开发时切换路由,会触发页面重载,而Rsbuild则不会。
之前转发过Rsbuild发布1.0的文章,字节团队的口碑还是有保障的,有需要的小伙伴们可以考虑用起来了。