辛宝Otto

辛宝Otto 的玄酒清谈

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

速通-Rspack 相關技術分享

image.png

Rspack 是一個很好的技術話題,也是未來的播客嘉賓,這裡做個快速了解。

這次帶讀的是字節跳動 Rspack 的原理與實踐,字節跳動楊健
楊健 - 字節跳動 Rspack 的原理與實踐

官網 rspack.dev

以下是一些分享內容的原文和感受,原文我會註明,以感受為主。

image.png

原文大綱

  • 為什麼選擇 Rspack
  • 特性
  • 生態兼容
  • 開箱即用的能力
  • 業務性能收益
  • 架構設計
  • 遷移指南

為什麼選擇 Rspack#

webpack 不夠好#

公司內部有很多巨型應用,項目啟動慢,冷啟動慢、構建慢。

傳統的 webpack 優化手段已經老套,例如 babel -> swc-loader,例如 esbuild/vite 等。

這些方案有優勢,但不能完全解決問題。例如 swc-loader 可以加速 loader,但不全面。

vite 的 dev 快,但是 rollup 構建速度並不比 webpack 快。

esbuild 在生產優化方面很快,但是不支持 dev-hmr,打包能力和插件能力都比較弱,無法滿足拆包需求。

這裡回答了 vite 和 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 提升了 10 倍。

webpack 中一個 hrm 需要 20 秒,不敢想像...,優化後只需要 1 秒。

常見問題#

所以可以回答一些常見問題:

為什麼不是 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 圖形創建
    • 分包、模塊圖
  • id 生成
    • 生成模塊 id
    • 生成 chunk id
  • 模塊代碼生成
  • 運行時模塊
  • chunk 資源生成
  • 生成資源

分包緩存策略,要和業務區分,拆包並行加載。
用戶配置 polyfill es5-es6-esnext 等
這一部分很精彩,第一次聽。

image.png

黃色部分都是可以並行處理的,rust 做得比較快。webpack 做不好的一個原因是對多線程處理不好,使用 thread-loader 也會通信費勁,但是 rspack 兩個缺點都解決了。

核心:一切能並行的地方都並行。多核提升一倍,能有 1.7 倍的提升,當然還是有損耗的。但是比 webpack 提升有限,例如 1.1 倍 - 1.2 倍的提升有限。

老業務遷移#

  • 內置的功能要使用,例如 js/ts/css/file-loader/html-plugin 等
  • 例如 html-plugin 插件的靈活度不夠好,畢竟 html 那個業務都想塞點東西進去,所以這裡也內置了一個 js 版本的插件用來方便擴展,稍慢但靈活
  • 第三方插件不支持,可以跟進

roadmap 展望

  • webpack 生態兼容
  • 更多框架支持
  • 支持持久化緩存 persistent cache、懶編譯 lazy compilation
  • 更多生產優化
  • 支持 mf

聽完的展望#

呼,帶讀了 webpack 的架構,指出了優化方向,那麼 rspack 就是這樣做的。

尊敬深厚經驗,細節還是不懂,得多看。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。