- Published on
JSDC 2024|一起探索 VoidZero 為 JS 生態系準備的瑞士刀
- Authors
- Name
- CK Chuang
- @codefarmer.tw
目錄
- Intro.
- Build tool vs Bundler
- VoidZero 是什麼?
- Vite 介紹
- VoidZero 工具鏈介紹
- Oxc 介紹
- Demo
- Vitest Demo
- Oxc linter Demo
- 總結
- 收尾
- Q&A
- 1. 因為這些新潮的工具都開始轉往 Rust,請問您認為前端人員需要學習 Rust 嗎?
- 2. VoidZero 怎麼賺錢為什麼會有人願意投資?
- 3. 對 build tool 到 bundle 打包工具 (包含 compiler) 之間的關係仍然很不熟悉, 有推薦的學習資源 (有助於了解整個 flow) 嗎?
- 4. 請問Vite是不是不能適用於非模組化的前端舊專案?
- 5. vite 開發時是用 esbuild 打包,正式機是用 rollup 打包。想問如果在 vite config 做以下設定 build: { minify: 'esbuild' ...},正式機也會變成用 esbuild 打包嗎?
- 相關連結
感謝 JSDC 2024 主辦方的邀請,有機會能夠於今年末初試啼聲進行一場短講,這次的主題是《一起探索 VoidZero 為 JS 生態系準備的瑞士刀》,希望能由淺入深地介紹 Vite、Vitest、Rolldown、Oxc 組成的生態系。
這次的簡報是使用 Slidev 實作,並有部署在網頁上,所以其實也可以直接開 Presenter Mode 就能看逐字稿,但目前在 Chrome 看似乎有一些動畫不順的問題,可先用 Safari 瀏覽體驗更佳,以下也順手輸出記錄一下。
而關於心得與紀錄的部份,也另外拆去另一篇《第一次當技術講者紀錄與心得》做個紀錄,有興趣看我 murmur 也是可以參考看看。
Intro.
Hi 大家好,很高興今天有機會來 JSDC 分享,然後這也是我第一次當講者,希望大家會喜歡。
今天要分享的主題是《一起探索 VoidZero 為 JS 生態系準備的瑞士刀》。
那這把瑞士刀裡會包含 Vite、Vitest、Rolldown、Oxc 這些工具,接下來就會帶大家了解一下,並做一些 Demo。
那先簡單做一下自我介绍!我是 CK,之前在幾間公司擔任前端工程師。這一年開始經營 codefarmer 這個部落格,今天的投影片過幾天整理後也會放到上面,如果大家對今天的主題有興趣或問題,都可以從部落格上找到各種聯絡資訊跟我討論。
Build tool vs Bundler
在最開始先快速帶過一些後面講解會需要知道的基本介紹。
首先是 Build Tool 和 Bundler 的差別。中文也有人翻作「建構工具」跟「打包工具」。 大家可以暫停兩三秒,想一下這兩者的差別是什麼?
簡單說的話,當你今天想做一個網站,從在 local 開發到最後部署到雲端伺服器, 這個開發過程中在處理網頁畫面的部分,背後可能有機會去用上這兩種工具。
建構工具的部分可以理解為你在開發時下了 npm run dev
這樣的指令後, 會在 local 去啟一個 dev server 來協助你邊寫程式邊確認畫面。
因為在開發過程中,可能會用一些像是 typescript、scss 這些語法來協助開發。
等開發都完成後,要準備部署時, 因為瀏覽器本身是不認得這些語法的, 所以這時候就需要用「打包工具」去設定一些 loader 和 plugin, 來將這些語法轉譯後,再去做 minify、uglify 等動作。 最後打包出瀏覽器能看懂的 HTML、CSS、JS 檔案。
從這張圖上可以看到這兩者對應的工具,像大家比較常聽到的 Webpack 是打包工具, 而對應以前可能會有 Create React App 或 Vue CLI 或 webpack-dev-server
就是建構工具。
而今天要介紹的 Vite,本體其實是建構工具,背後打包的工作目前是使用 Rollup。
另外還有在今年剛正式釋出第一版的 Rspack,這套是由 ByteDance 的 infra 團隊用 Rust 去開發,也有分成 Rsbuild 與 Rspack。
VoidZero 是什麼?
再來講講 VoidZero 是什麼?VoidZero 是一間公司。它是由 Vue 跟 Vite 的作者尤雨溪先生,在今年 ViteConf 時宣布募資成立的新公司。
那它的願景是希望能打造一個從建構工具的 Vite,單元測試框架的 Vitest,到打包工具的 Rolldown,再到底層編譯工具的 Oxc,一整個完整的開源工具鏈。那為什麼會有這個想法呢,這邊就先來簡單介紹一下 Vite。
Vite 介紹
就像前面提到的,Vite 是一個建構工具。如果你曾經有在開發一些前端專案時玩過 Vite, 會發現比起過往用其他 bundled-based dev server, 像是 CRA 或 Vue CLI 的體驗快很多。
其中一個主要原因是因為他利用了瀏覽器原生支援 ES Module 的特性,來提升開發體驗。
再深入看到這張圖是 Vite 目前的架構。簡單說的話會由 esbuild 負責 local 開發時的 pre-bundling。 把專案中的依賴套件做預先打包與快取,可以解決像是 request waterfall、不同套件模組標準不同的問題。
而 Rollup 會負責 production 打包。SWC (Speedy Web Compiler) 做為 Rollup 目前底層的編譯器。
而會想要開發整套工具鏈的原因是因為一些問題:
esbuild 是用 Go 寫的,效能快, 但缺點是目前在 code-splitting、tree shaking、plugin 生態系這些功能的不齊全,在 production 打包時不能用。
而 Rollup 的好處是有完整的 plugin 生態系,但效能比不上其他靜態語言為基底的打包工具。
因為現在 dev/production 分成 esbuild 與 Rollup 兩套,所以有時會有兩種環境行為不一致或像是模組轉換的問題。造成 debug 不容易。
另外多套工具間的 build pipeline 中會有不少轉譯語言成本的浪費。
為了解決以上這些問題,在去年時 Vite 團隊原本與 Rspack 團隊,決定一起開發 Rolldown 這套用 Rust 寫的打包工具。想換掉原本底層使用的 esbuild 與 Rollup。
但當團隊越鑽越深時,發現如果不一次做到好,底層的這些多套工具交互的問題可能仍會重演, 讓不同 JS 生態系的底層仍需要同時仰賴多套工具。 因此決定把夢做大成立一間獨立的開源公司來把整套工具鏈做得更完善。
因為這個過程就需要更多的開源開發者加入,也不能讓贊助資源只集中在某些人身上,所以成立公司來整合整個資源。
VoidZero 工具鏈介紹
接下來講一下其他工具的細節。看回右邊這張圖。
今天當我們用 React, Vue, Nuxt, Remix, Astro 等這些上層前端框架或 meta framework 時,現在預設都能夠以 Vite 作為建構工具。
另外可以搭配能這個兼容 jest 的單元測試工具,Vitest。以前如果在 Vite 專案中要能使用 jest 時,會遇到一些轉換與設定問題,所以後來 vue 的核心開發者 sodatea 幫忙做了一個叫做 vite-jest 的工具。(ref)
後來為了能在設定時更方便去與 Vite 整合,因此後來 Vite 核心團隊 (Antfu, Patak 等人) 開發這套 Vitest。
再來是 Rolldown 的部分,就像前面提到的目前正在開發中。希望能利用 Rust 打造一個打包工具,來解決目前底層在 dev/production 用兩套打包工具的問題。就像另一套以 Rust 為基底打造的 Rspack 能兼容 Webpack 的方式一樣,或許未來有機會能夠兼容目前所有的 bundler,如果在生態系接受度夠高的狀況下。
最後是 Oxc。這個工具大家可能相對更陌生,另外拉出來特別講一下。
Oxc 介紹
Oxc 是 Oxidation Compiler 的縮寫,這算是一整套用 Rust 去寫的,比較底層的編譯與解析語法的工具。Oxidation 這個字是氧化的意思,而 Rust 是生鏽的意思,
雖然沒查到相關資料,但猜測是想表示把一些工具改成 Rust 的版本,所以取這個名字。
像是比較常見的 linter 的部分可以對應到原本的 eslint,formatter 的部分可以對應到常見的 prettier,transformer 主要是在處理語法轉譯,對應到大家可能聽過的 Babel、SWC、tsc。目前後面這三者都還在開發中,所以今天只會先試試看 linter 的部分。
從上面這些比較,如果稍微了解過一些 Rust 的特性的話,會知道 Rust 因為提供更有彈性的記憶體管理系統,所以被應用在這些底層工具上能有效提升效能。
可以理解為 Oxc 的目標想把以前我們常用的一些工具像是 Babel、ESLint、tsc、prettier 等,用 Rust 改寫來做一個效能提速,但本質上並不是想取代這些工具,後面會提到。基本上跟另外一個叫做 Biome 的工具鏈是同樣的目標,Oxc 的文件上也有提到他也受到 Biome 跟 Python 生態系的 linter — Ruff 的啟發。
Demo
Talk is cheap, show me the code.
接下來我們簡單看一下要怎麼用這些工具。首先先來看一下 Vitest 的部分,這裡我有拿我以前一個有幾個單元測試的專案來示範。會後有興趣可以參考投影片裡面連結的這個 repo. 來試玩看看。
Vitest Demo
先看到 vitest 基本設定檔的部分。首先你可以注意到,這裡直接將 vitest 的設定寫在 vite.config.ts
裡, 或你想另外寫成獨立設定檔也可以, 這裡的第 2 行是為了讓 TypeScript 能正確去解析 vitest 的設定型別。
往下快速帶大家看幾個重要的設定,在 jest 中預設會開啟全域載入的設定, 也就是你不需要在每個單元測試檔裡去載入那些 describe
、expect
之類的函式。 想要在 Vitest 中達到一樣效果的話可以把這個設定打開。
再來這個 environment
的部分。預設測試會跑在 node
這個環境下,但當今天需要跟 testing-library 整合去做元件測試的話, 可以改成 happy-dom
或 jsdom
這個環境,這樣可以更方便的模擬 DOM 環境。
然後從 happy-dom 從 benchmark 看比較快一些, 但相對在套件大小、功能性上沒有 jsdom 全面。
再來這個 setupFiles
的部分, 這裡可以做一些初始設定, 像這裡去載入 testing-library 相關套件, 並考慮在每個測試後去清掉不必要的元素避免互相污染與效能緩慢的問題。
最後也可以做一些涵蓋率報告的輸出跟 alias 的設定等等。
再來簡單看一個單元測試的範例。
像圖上這段關於 sleep 這個函式的單元測試,假如原本是用 jest 去實作的話會長這樣。這裡可以看到有用上像是 useFakeTimers
、advanceTimersByTime
這些用來模擬時間的函式。
如果今天要改成 Vitest 的話,只有一些像是 mock function 或模擬時間部分要從 jest
改成 vi
這樣。其他主要的 beforeEach
、afterEach
、describe
、expect
這些方法都有兼容。所以在做 jest 到 Vitest 的 migration 時會蠻方便的。
再來簡單看一下 Vitest 執行測試的 demo。這裡看到我在 package.json
裡面有設定三個指令,分別能直接執行測試、或也支援 watch mode 能利用 vite 的 HMR 特性監聽修改的測試檔變化來方便開發。還有一個比較酷的是有提供一個類似 devtool 的 Vitest UI。
我們來看看實際執行的畫面。
可以看到這裡我假裝讓某個元件測試 fail,你可以在 UI 介面去確認錯誤訊息。 也有一些視覺化的模組依賴畫面等等。
這個 demo 中我沒有特別做效能比較,但根據網路上的 benchmark 看起來大多會比 Jest 快兩三倍以上。 因為 Vitest 原生支援 ESM 與 TypeScript, 加上與 Vite 的整合,因為底層有用上 esbuild 來解析語法,所以效能會比較好。
稍微小結一下,像前面說的 Vitest 的特色主要有幾點:
高度與 Jest 兼容
原生支援 ESM 與 TypeScript (以前在 jest 可能需要安裝一個 ts-jest 的 preset)
能與 Vite 更緊密整合 (能直接寫在 vite.config.ts 裡)
效能比 Jest 快一些
Oxc linter Demo
最後來看一下 Oxc 裡的 linter 要怎麼試玩。
這裡因為手邊沒有太複雜的專案,參考 Evan 當初發現這個工具時的敘述,我們就直接用 vue 的原始碼來跑跑看。
這裡如果試著將專案載下來後,去用不安裝套件的方式執行指令,看要使用哪種 package manager 都可以。執行完後會看到像圖上這樣,對 500 多個檔案去做 lint 分析,只跑了 200 多毫秒。
目標不是在取代 ESLint,畢竟 ESLint 生態已經廣為使用,主要是當今天有複雜專案在部份 workflow 像是 lint-staged 或 CI 上去跑 ESLint 檢查程式碼品質,當今天在這部份遇到瓶頸時,可以嘗試用 oxlint 來改善效能。
目前也有提供 VSCode 體系的擴充,但這部份我沒研究太多,可以再試試看。然後參考文件說明,目前 oxlint 只支援約 400 個規則,如果想提前與 ESLint 整合的話,可試試 eslint-plugin-oxlint
這個 plugin,並在 package.json 裡的 lint-staged 設定這樣改:
總結
看完今天分享你可能會想說新工具好潮,下週我就來翻新公司專案。只能跟你說「修但幾咧」。
有句老生常談的話是新東西很潮很快沒錯,但在應用到正式產品上之前,最好是能先用一些實驗型的小專案玩玩看,也需要考量到團隊資源與產品穩定性等問題。況且新潮的東西不一定在五年十年後會流行,只能讓子彈再飛一會兒。
最後做一下總結。今天我們介紹了 VoidZero 底下的生態系,包含 Vite、Vitest、Rolldown、Oxc 這些工具。然後也要提醒大家,不要覺得新技術很多感到焦慮,可以先了解觀望即可。
最後有個有趣的觀點是我在看國外社群討論 VoidZero 時看到的,就是畢竟 VoidZero 是一間「公司」,但本體是個開源軟體生態系他本身該如何賺錢,而創投的 Accel 又為什麼願意投資他們?「過往在 VC 介入開源的經驗並不好」,可能是想想 Joynt 之於 Node.js、Vercel 之於 Next.js、Meta 之於 React 等等。
有一說是未來 VoidZero 這間公司會開發一些非開源的工具解決方案,來協助大企業做一些工具效能的提升,並有效減少機器成本來盈利。或是利用 Vite 的廣大使用者,未來跟這些投資的雲端公司合作,提供一些一鍵完成像是發電子信、監控等整合方案。
收尾
- ViteConf 2024
- Vitest 相關
- Rolldown、Oxc 相關
- VoidZero 相關
這裏附上一些參考資源,有興趣深入研究可以看看。
以上就是我今天的分享,簡報原始碼與 demo 連結目前已經放在這個 repo 與這個網址上,也特別感謝 Kevin Deng、Anthony 在 Slidev 工具與主題的開源。
關於今天演講,因為時間有限,若有任何回饋或問題,歡迎加 IG 與我聯絡。謝謝大家,祝大家週末愉快!
Q&A
1. 因為這些新潮的工具都開始轉往 Rust,請問您認為前端人員需要學習 Rust 嗎?
個人認為算是加分項,因目前求職市場上確實針對此技能沒這麼必要,把基本功打穩可能更有幫助。但如果行有餘力當作興趣去學習新語言 Rust 的特性可以對像是記憶體管理等概念更有掌握度。
2. VoidZero 怎麼賺錢為什麼會有人願意投資?
時間因素來不及講到,不小心準備太多內容了😅。我看到有說法像是從 VoidZero 官方公告 中的這段可以看到:
On top of our open-source projects, we will offer an end-to-end JavaScript tooling solution specifically designed to meet the scale and security requirements of enterprise environments.
看討論在猜測有可能未來有機會去提供企業閉源的整合式解決方案。或是類似像是置入的方式來做雲端、託管服務的整合,例如說去與電子信服務商 Resend 用 Vite 整合,當你今天想用 Vite 去做電子信就可能會一起買 Resend 方案等等。
3. 對 build tool 到 bundle 打包工具 (包含 compiler) 之間的關係仍然很不熟悉, 有推薦的學習資源 (有助於了解整個 flow) 嗎?
這場短講中因為時間因素所以帶的比較快,有興趣深入研究可以參考我部落格上這個關於 前端工具 的系列。其中也有附上許多學習資源可以參考,或有問題歡迎加我 IG 一起交流!
4. 請問Vite是不是不能適用於非模組化的前端舊專案?
不確定整個舊專案的脈絡是什麼,但因為 Vite 標配會需要能用 ES Module,如果專案舊到是用純 HTML 包 CommonJS、AMD 等 script 的方式,或有用傳統 SSR 的 template engine,有可能會需要一個漸進式的遷移計畫來改善開發體驗:
- 模組化
- 先將舊模組遷移至較現代的 ESM
- 前後端分離
5. vite 開發時是用 esbuild 打包,正式機是用 rollup 打包。想問如果在 vite config 做以下設定 build: { minify: 'esbuild' ...}
,正式機也會變成用 esbuild 打包嗎?
查了 Vite 關於這個設定的文件 (ref),看起來指的是在 production build 時的 minification 工具想使用 esbuild 來幫忙做。
我的理解是在使用 Rollup 設定去做打包時,將其中的 minify 這件事外包給 esbuild 去做,因為 esbuild 本身也是有提供 minifier 的 API 可以用 (ref)。但實際是不是這樣可能要實驗看看或簡單追追看這個設定的原始碼才能確定,你可以再朝這個方向試試,有遇到問題歡迎加我 IG 一起交流!