辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

速通-Rspack 相关技术分享

image.png

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 就是这样做的。

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

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。