Rsbuild项目迁移尝鲜

1,564 阅读5分钟

看了这篇《开发体验的彻底提升,从 Vite 迁移到 Rspack》,作者提到RsbuildRspack对标WebpackRsbuild进一步封装,提供大量开箱即用的功能,体验类似于Vite),相比于Vite的优势:

  1. Rspack解决了页面加载速度瓶颈问题,其构建机制不会导致页面请求数过多;
  2. 开发环境与生产环境一致(Vite将来使用Rolldown可解决);
  3. 打包速度惊人,项目打包速度提升 80% 以上,使开发流程更流畅。

有些心动。

于是,我决定尝试把现有项目改造成 rsbuild,看下到底有多大的提升。

这是一个rsbuildv1.0.4)的配置文件,用到了ElementPlus免引入,httpssass,所以配置麻烦一些:

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相比,RsbuildRust的加持,完全是碾压的优势,全方位降维打击。

开发体验上,原来Webpack dev启动弹出了页面,但要过差不多15秒才能看到页面,而改造后与Vite体验一样,秒开,太丝滑了。

这个我并不意外。

有些意外的是,我的Vite项目,一个后台管理页面,在开发阶段消除了我一个困扰多时的问题。

改造前某个路由里有159JS请求:

改造后只在16JS了:

项目没到作者的体量,所以页面加载时间上二者差距不是很大。我说的意外是,项目里用到了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改造后,解决了。仔细一想,意料之外,情理之中。

这里贴一张原文描述RsbuildVite随着源文件数量的增加页面重载速度曲线图:

改造细节

大部分情况下,只需要进行配置文件的修改,按照官方的迁移指南进行就可以了。

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

  1. GitLab流水线的构建环节上,相比于Webpack9倍的差距,相比于Vite3倍的差距。
  2. 在开发阶段,与Vite类似同样做到了秒开,且由于加载机制的不同,在源码文件巨多时会有更大体验优势。我的项目中用到动态注入ElementPlus的引用,在Vite开发时切换路由,会触发页面重载,而Rsbuild则不会。

之前转发过Rsbuild发布1.0的文章,字节团队的口碑还是有保障的,有需要的小伙伴们可以考虑用起来了。