尤雨溪:Turbopack 真的比 Vite 快 10 倍嗎?

大家好,我是 CUGGZ。

10 月 25 日,Vercel 推出了下一代打包工具:Turbopack,它是基於 Rust 的 Webpack 繼任者,其文檔中提到,Turbopack 比 Vite 快 10 倍。11 月 1 日,Vue、Vite 作者尤雨溪發表文章 《Is Turbopack really 10x Faster than Vite?》,對 Turbopack 和 Vite 進行了測試對比,下面就來看看詳細內容吧!

在 Turbopack 官方文檔的基準圖中,最初顯示帶有 Turbopack 的 Next 13 能夠在 0.01 秒內執行 React Hot-Module Replacement (HMR,即熱更新),而對於 Vite,則需要 0.09 秒。上面也有冷啓動性能基準,但由於沒有一個冷啓動基準顯示出 10 倍的優勢,我們只能假設 “快 10 倍” 的說法是基於 HMR 性能。

Vercel 並沒有在文檔中包含指向他們用來生成這些結果的基準的任何鏈接。所以,尤大決定使用新發布的 Next 13 和 Vite 3.2 來驗證這些聲明。測試的要點是通過測量以下兩個時間戳之間的增量來比較 HMR 性能:

該基準還測量了兩種不同情況下的結果:

細微差別

在測試這些之前,還有一些額外的細微差別值得一提:

React 服務端組件

Next 13 引入了一個重大的架構轉變,現在的組件默認爲服務端組件,除非用戶使用 “use client” 指令明確選擇客戶端模式。它不僅是默認設置,Next 文檔還建議用戶儘可能保持服務端模式,以提高最終用戶的性能。

第一輪測試(Next w/ RSC 和 Vite w/ Babel))

最初的基準測試是在服務端模式下使用根組件和葉子組件測量 Next 13 的 HMR 性能。結果表明,Next 13 在兩種情況下實際上都較慢,並且對於葉子組件而言差異顯著,測試方法和測試結果如下。

① 測試方法

  1. 這兩個項目都是通過以下命令新創建的:
npx create-next-app@latest
npm init vite@latest  # 選擇React預設
  1. 在每個項目中運行 genFiles.(m)js 生成 1000 個組件,所有組件都被導入到應用的根組件中並一起渲染。

  2. 對於每個項目,在單獨的 Node 進程中運行 watch.(m)js 以獲取文件更改的確切時間戳,這用於標記 HMR 的開始。

  3. 啓動項目,然後編輯以下文件以測試 HMR:

已編輯的組件都在其輸出中包含 Date.now()。DOM 中最終渲染的時間戳用於標記 HMR 的完成。

② 測試結果

第二輪測試(Next w/o RSC 和 Vite w/ Babel))

有人指出,應該在沒有 RSC(React 服務端組件)的情況下對 Next 組件進行基準測試以使其相等。因此,在 Next 根組件中添加了 “use client” 指令以選擇客戶端模式。事實上,在客戶端模式下,Next HMR 顯着改進,比 Vite 快 2 倍,測試方法和測試結果如下。

① 測試方法

  1. 這兩個項目都是通過以下命令新創建的:
npx create-next-app@latest
npm init vite@latest  # 選擇React預設
  1. 在每個項目中運行 genFiles.(m)js 以生成 1000 個組件。所有組件都被導入到應用的根組件中並一起渲染。

  2. 給 app/page.js 添加 use client 指令,使它以客戶端模式渲染。這是確保正確的比較所必需的,因爲服務端組件會產生不小的 HMR 開銷(慢 4 倍)。

  3. 對於每個項目,在單獨的 Node 進程中運行 watch.(m)js 以獲取文件更改的確切時間戳。這用於標記 HMR 的開始。

  4. 啓動項目,然後編輯以下文件以測試 HMR:

② 測試結果

SWC 與 Babel 轉換

我們的目標是讓基準只關注 HMR 性能差異,所以需要消除另一個變量:Vite 的默認 React 預設使用 Babel 來轉換 React HMR 和 JSX。

React HMR 和 JSX 轉換不是與構建工具耦合的特性,它可以通過 Babel(基於 JavaScript)或 SWC(基於 Rust)來完成。Esbuild 也可以轉換 JSX,但缺乏對 HMR 的支持。SWC 比 Babel 快得多(單線程時快 20 倍,多核時快 70 倍)。Vite 目前默認使用 Babel 的原因是安裝大小和實用性之間的權衡。SWC 的安裝量相當大(node_modules 中有 58 MB,而 Vite 只有 19 MB),並且許多用戶仍然依賴 Babel 進行其他轉換,因此 Babel 對他們來說是不可避免的。但是,這種情況在未來可能會發生改變。

Vite core 並不依賴 Babel,因此使用 SWC 而不是 Babel 來處理 React 轉換不需要在 Vite 中進行任何更改,只需將默認的 React 插件替換爲 vite-plugin-swc-react-refresh。切換後可以看到,Vite 在根組件中有顯着提升,趕上了 Next:

有趣的是,這裏的增長曲線顯示 Next/turbo 在根組件比葉子組件中慢 4 倍,而 Vite 只慢 2.4 倍。這意味着 Vite HMR 在更大的組件中可伸縮性更好。此外,切換到 SWC 還可以改善 Vite 在 Vercel 基準測試中的冷啓動指標。

不同硬件上的性能

由於這是一個涉及 Node.js 和原生 Rust 部分的複合基準測試,因此在不同的硬件上會有很大差異。以上結果是在 M1 MacBook Pro 上收集的。其他用戶在不同的硬件上運行相同的基準測試並報告了不同的結果。在某些情況下,Vite 在根組件情況下更快,而在其他情況下,Vite 在兩種情況下都明顯更快。

Vercel 的澄清

在尤大發布了自己的基準後,Vercel 發佈了一篇博客文章,闡明瞭他們的基準方法,並將他們的基準提供給公衆驗證。閱讀文章和基準代碼後,以下是一些關鍵點:

總而言之,如果以下所有條件都成立,“比 Vite 快 10 倍” 的說法是成立的:

什麼是 “公平” 比較?

如果我們要比較的是 “開箱即用的默認設置”,那麼我們應該與 Next 中啓用的 RSC 進行比較,因爲這是默認設置,也是 Next 積極鼓勵用戶使用的。由於 Vercel 的基準測試沒有使用 RSC,並且正在測量 “模塊評估時間”,以排除 React 的 HMR 運行時引起的差異,因此可以公平地假設基準測試的目標是對 Vite 和 Turbopack 固有的 HMR 機制進行比較。

不幸的是,在這個前提下,Vite 仍然在基準測試中使用 Babel 使這個對比是不平等的。在 Vite 中使用 SWC 進行轉換更新對比結果之前,Turbopack 比 Vite 快 10 倍的結論是不準確的。

此外,我相信大多數人都會同意:

作爲 Vite 的作者,很高興看到像 Vercel 這樣資金雄厚的公司在改進前端工具方面進行了大量投資。在適用的情況下,甚至未來可能在 Vite 中利用 Turbopack。然而,開源工具的競爭應該建立在公開溝通、公平比較和相互尊重的基礎上,令人失望和擔憂的是,看到激進的營銷使用了精心挑選的、未經同行評審的、邊緣誤導性的數字,這些數字通常只在商業競爭中出現,相信 Vercel 可以做得更好。

相關鏈接

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/RhRaMFmkEf4kxgFgcvr_4w