辛宝的玄酒清谈!
1594 words
8 minutes
速通-Rspack 相关技术分享
2023-10-25

速通-Rspack 相关技术分享

Rspack 是一个很好的技术话题,这也是未来的播客嘉宾,这里做个快速了解。

这次带读的是字节跳动 Rspack 的原理与实践,字节跳动杨健 杨健-字节跳动 Rspack 的原理与实践

官网 rspack.dev

一些是分享内容的原文和感受,原文我会注明,以感受为主。

image.png

原文大纲

  • why Rspack
  • 特性
  • 生态兼容
  • 开箱即用的能力
  • 业务性能收益
  • 架构设计
  • 迁移指南

why Rspack#

webpack 们不够好#

公司内部巨型应用多,启动项目慢,冷启动慢、构建慢。

传统 webpack 的优化手段,老一套,也比如 babel -> swc-loader,比如 esbuild/vite 等。

这些方案有优势,但不能完整解决。比如 swc-loader 能加速 loader,但不全面。

vite 的 dev 快,但是 rollup 构建,并不比 webpack 快。

esbuild 生产优化很快,但是不支持 dev-hmr,打包能力插件能力弱了很多,拆包需求满足不了

这里就解答了 vite and rspack 哪个好的问题,这个没有答案。看场景和极端表现。比如开发体验、ssr,但是重型项目的构建就有差异了。

但是 rspack 本身偏底层,vue-cli 迁移会麻烦些。

好的构建工具什么样#

也就是开发者的诉求

  • 性能要好,冷启动快、hrm 快、构建快,构建几十次的情况下。
  • 灵活性,配置要灵活,应对不同的使用场景。toC 构建产物大小、和 toB 巨型应用伸缩性
  • 生产产物性能:code splitting 拆包、treeShaking、首屏等
  • 应用场景,webapp+node.js+跨端
  • 迁移成本要低,业务方不抵触

这样看下来,webpack 是最好的,比如 swc/esbuild/vite 等工具面对传统项目、跨端项目还有很长的路要走。

rspack 说我来!#

rspack 呼之欲出,优点不少:

  • rust 实现,原生能力强
  • 增量编译、hrm 快
  • webpack 生态兼容
  • 开箱即用支持 ts/tsx/css/css modules,不用自己找插件了
  • 默认多种优化策略,tree shaking/code splitting 代码压缩等

兼容性好,举例了一部分。那么我们常见的插件都看到了。

image.png

还有,ts 不用自己折腾了,默认的又快用好,babel-loader/ts-loader 不需要了,啊曾经的噩梦。

css 之前很麻烦,抽包、css/style loader 等,现在也内置了,又快用好,但 less/sass 还需要配置,有个对比截图,rspack 简单一些,主要是 less-loader 结束产物直接设定 css 和 css/module 给内置处理。

说完兼容性,性能收益好,三个指标冷启动 dev、hrm、生产构建 build。

给了一张图,不放了,就是 rspack 表现很不错。尤其是生产构建 rollup 还是不行。

收益#

说完跑分,说落地。内部项目跑下来提升巨大,相较于 webpack 10x 提升。

webpack 里一个 hrm 有 20s,不敢想象…,优化后 1s。

常见问题#

所以可以回答常见问题了:

为什么不是 node + js?#

  • webpack 单线程多年努力,性能压榨有限
  • node 本身是单线程,本身不能多线程
  • 使用 worker-thread 支持多线程,背后是创建新的 v8 实例模拟单线程。通信的过程需要序列化和反序列化,数据共享效率不高
  • 并发生态匮乏 因为 v8 多线程支持不够好,性能消耗大,并发编程生态匮乏

为什么不是 golang - esbuild?#

  • golang 性能满足
  • 对 napi 支持不好,所以无法满意
  • esbuild 不提供操作 ast 的 api,不支持降级 es5

为什么是 rust?#

  • 性能好
  • 对 napi 支持好,rust 宏支持,少写样板代码
  • rust 对 webAssembly 支持好,甚至 rust 推动更激进领先
  • rust 的 swc 对 ast 的操作支持丰富,也支持降级 es5

swc 就好吗?#

大厂秀实力,

  • 发现 swc 并发解析差,发现 dev 的 profiler 发现 parsing 是瓶颈,进一步发现了底层库的 bug

为什么还要使用 js 做插件拓展呢#

  • js 熟悉,rust 不熟悉,成本高,不能满足灵活多变
  • 动态化特性,rust 动态性不如 js,比如编译产物可能和机器环境相关,可能有差异,跨平台的处理麻烦,可能需要编译出十几个平台的产物,门槛高,稳定性也不够强

快的原理#

  • 架构基于 Webpack 5
  • 拥抱 rust
  • babel 换成 swc,loader 太慢了,大家一般使用 swc/esbuild 提速。
  • rust 和 js 使用 napi-rs 通信,v8 是基于 buffer string 通信,多线程支持不好,复杂的数据结构通信困难,比如 ast 只能选择序列化通信。序列化反序列化开销巨大。但是 rust 多线程共享简单,没有什么开销。多核表现优异。

放了一张架构图,我没见过,说是和 webpack 架构图差不多。(这里我没经历过,我听了两次)

make pase 构建依赖图 module graph /seal phase 阶段。依赖图生成 chunk

  • 优化分析,分析模块使用、副作用
  • chunk graph creation
    • 分包、模块图
  • id generation
    • gen module id
    • gen chunk id
  • 模块代码生成
  • 运行时模块
  • chunk 资源生成
  • 生成资源

分包缓存策略,要和业务区分,拆包并行加载。 用户配置 polyfill es5-es6-esnext 等 这一部分挺精彩的,第一次听。

image.png

黄色部分都是可以并行处理的,rust 做比较快。webpack 做不好一个是对多线程处理不好,使用 thread-loader 也会通信费劲,但是 rspack 两个缺点都处理了。

核心:一切能并行的地方都并行。多核提升一倍,能有 1.7x 的提升,当然还是有损耗的。但是比 webpack 提升有限,比如 1.1x-1.2x 提升有限。

老业务迁移#

  • 内置的功能要用,比如 js/ts/css/file-loader/html-plugin 等
  • 比如 html-plugin 插件做的灵活度不够好,毕竟 html 那个业务都想赛点东西进去,所以这里也内置了一个 js 版本的插件用来方便扩展,稍慢但灵活
  • 三方插件不支持,可以跟进

roadmap 展望

  • webpack 生态兼容
  • 更多框架支持
  • 支持持久化缓存 persistent cache、懒编译 lazy compilation
  • 更多生产优化
  • 支持 mf

听完的展望#

呼,带读了 webpack 的架构,指出了优化方向,那么 rspack 就是这样做的。

尊敬深厚经验,细节还是不懂,得多看。

速通-Rspack 相关技术分享
https://ijust.cc/posts/quick-review-dd-rspack/
Author
辛宝 Otto
Published at
2023-10-25