什麼是 Oxc?什麼是 void(0)?
Table of Contents
前言
前幾天在 ViteConf 2024 時,Evan You 宣佈成立一間新公司 — void(0),目標在打造一整套開源、統一、高效能的 JavaScript 開發工具鏈。
今天在看完了這場 keynote 與後面 Oxc 專案的核心開發者 Boshen 的介紹後,認為核心開發團隊經過一年的研究後講的又更清楚了,因此也做了些筆記,那就讓我們快速了解一下這個 Oxc 跟這個 void(0) 是怎麼回事吧。
什麼是 void(0)?
Vite 現在的缺點與困境
雖然 Vite 生態系四年來成長速度很快,但這兩年都不斷提到目前有一些痛點:
esbuild
在 dev 中被拿來當 dep. pre-bundling (或稱 dep. optimizer) 的打包,但它在 code splitting、tree-shaking、plugin 的不足讓 Vite 無法完全用它做為統一的 bundlerRollup
打包速度太慢Rollup
目前底層用上的SWC
有執行檔過大的問題,舉例在 macOS 上 SWC 的 binary 檔案有 37MB,幾乎是 Vite 本身的兩倍多。且SWC
本身也沒有提供完整的 bundler 功能。esbuild
與Rollup
兩套 bundler 造成 dev / prod 行為不一致,有時會在上線後才發現 bug- 多套的工具造成 build pipeline 的過程中轉譯語言成本的浪費:
- 同樣一段程式碼,在 Vite 做 production build 時重複被解析成 AST、轉譯、序列化成字串
- 這些資料在這三個工具的原生執行環境中傳輸,像是從 Go process 傳到 JS main thread,再傳到 Rust,再傳回 JS,中間的轉換過程浪費成本
- 如果開啟 source map 的功能後上述的狀況會更糟糕,因為在每一步傳輸中都會需要重新映射(remapping)這些 source map 再去做合併
💡 補充:SWC 筆記
參考 SWC 官網介紹,整理一下筆記:
- 可以理解為更快的 Babel
- 因為是以 Rust 為基底做開發,比 Babel 快 20~70 倍 (隨著編譯時使用的硬體資源提升有所不同)
- 用途
- 主要用來轉譯 JS/TS 成瀏覽器可識別的一般 JS
- minification
- 可與 webpack 搭配 (swc-loader)
- 可用來增進 Jest 效能 (@swc/jest)
- 一些應該不太重要的業界冷知識
- SWC 原作者是個 1997 的韓國小哥 DongYoon Kang (kdy)
- Next.js 12 的文章中提到,目前 Vercel 已挖角了 SWC 作者 kdy 及 Parcel 核心貢獻者 Maia Teegarden,決心投資 Rust 生態系
為什麼要成立 void(0)?這是什麼?
綜上所述的問題,去年 Vite 團隊決定與 Rspack 團隊一同開發 Rolldown,但當團隊越鑽越深時,發現如果不一次做到好,底層的這些問題可能仍會歷史重演,JS 生態系的底層仍需要同時仰賴多套工具。
所以決定不要只停在統一 bundler 這一步,想要將底層工具鏈也全部串起來,也因此募資並成立了 void(0) 這間公司想打造一個全方位的 JS 工具鏈,希望能達到這樣的願景:
- 統一 (Unifoed):希望能在 dev / prod 轉換程式碼時都使用同一套工具、使用相同的 AST、同樣的設定、同樣的模組格式、路徑解析方式
- 高效能 (High Performance):做打包與轉譯等工作,應使用編譯型 (compiled-to-native) 語言,不僅可以增加 DX、加快產品交付,甚至能幫在座的各位省機器的成本
- 可組合 (Composable):工具鏈中的每一段應要是可獨立使用的,像是 parser、resolver、transformer 等,應該都要是一個套件,不論是 NPM packages 或是 Rust crates
- 框架不可知論 (Runtime Agnostic):這工具鏈應該不限制只能被用在某個框架中
什麼是 Oxc?
上面有看到在 Vite 的生態系中,Oxc
是一個可組合的語言工具鏈,其中含有一整套的 npm package 與 Rust crates,包含 parser、linter、formatter、transformer、minifier、resolver、semantic analysis 這些功能。
效能大比拼
或許你可能會對其中的這些工具感到困惑,直接看一下效能比拼中比對的對應工具,會看到一些熟悉的工具:
Oxc parser
比SWC
快 3 倍、比Biome
快 5 倍Oxc linter
(又稱oxlint
) 比ESLint
快 50~100 倍,當今天能擴充更多 CPU 核心時還能更快Oxc resolver
比webpack/enhanced-resolve
快 28 倍Oxc transformer
- TypeScript/TSX 轉譯:比
SWC
快 4 倍、比Babel
快 40 倍 - React Refresh:比
SWC
快 6 倍、比Babel
快 70 倍 - 產出 TypeScript 的聲明檔 (
.d.ts
):比tsc
快 20~45 倍
- TypeScript/TSX 轉譯:比
- Oxc 比起 SWC 與 Babel 有更少的記憶體使用與更小的套件與執行檔大小
而其中仍然有幾個工具我沒很懂它的用途,也做一下筆記:
- Parser 會用來解析 JS、JSX、TSX 並能生成 AST (Abstract Syntax Tree 抽象語法樹) 供後續 bundler 做語法分析,像是進入點在哪、需要轉譯成什麼模組、tree shaking 等
- Resolver 用來解析 Node.js 的模組路徑
- Transformer 利用 parser 產出的 AST,分析並轉譯出需要的 JS 檔案
從上面這些比較,可以理解為 Oxc 的目標想把以前的一些工具像是 Babel、ESLint、tsc、prettier 等 JS 開發工具鏈用 Rust 改寫來做一個效能提速,基本上跟另外一個 Biome 是同樣的目標,都想以 Rust 來實現更快速的工具。
Oxc 進度
但比較可惜的是目前這個工具鏈還在開發中,目前只有其中幾個工具可使用,在想可能等它再穩定些再回頭來學習,目前只有在 Oxc playground 上玩過:
原本只是個 side project
補充一個可能不太重要的冷知識,Oxc 核心開發者 BoShen 在議程中提到,這個 Oxc 最一開始只是他基於學習 Rust 的 side project,先是學著用 JS/TS 如何寫出 parser、linter 等,再進階到做出一個 Rust 版的 oxlint
並發佈這個工具,而後來 Preact 作者 Jason、和 Evan 都嘗試將 oxlint
拿來替代原本的 Linter 發現在大專案中的效能節省了數倍,因此才有了今天的故事。
小結
今天透過觀看 ViteConf 2024 更了解到 void(0) 這個前陣子在社群上引起討論的消息,知道它旨在打造一個全方位的 JS 工具鏈,而其中的這個 Oxc 將在未來做為其他工具的底層,來提供可在所有框架間組合的 parser、linter、transformer 等工具。
也趁機會了解了這些底層工具的用途,如果有什麼問題也歡迎在下面留言告訴我,我們明天見!