尤雨溪迴應:Vite 真的比 Turbopack 慢 10 倍嗎?

2022-11-09 22:00:37

前端(vue)入門到精通課程:進入學習
Apipost = Postman + Swagger + Mock + Jmeter 超好用的API偵錯工具:

原文:https://github.com/yyx990803/vite-vs-next-turbo-hmr/discussions/8

作者:尤雨溪

一週前,Vercel 宣佈了 Webpack 的基於 Rust 的繼任者 Turbopack。

在公告中,Turbopack 宣稱「比 Vite 快 10 倍」。 Vercel 的各種行銷材料都重複宣揚這句話,包括推文,部落格文章和傳送給 Vercel 使用者的行銷電子郵件。Turbopack 的檔案中還包括了 benchmark 圖,最初表明,使用 TurboPack 的 Next.js 13 可以在 0.01s 中執行 React HMR 熱更新,而對於 Vite 來說需要 0.09s。也有用於冷啟動效能的 benchmarks,但是由於沒有發現冷啟動速度是 Vite 10 倍的比較,因此我們只能假設「10 倍快」是基於 HMR 的效能。【相關推薦:、】

Vercel 沒有在行銷材料或檔案中使用用於論證這些數位的 benchmarks 的任何連結。因此,我很好奇,並決定使用剛釋出的 Next 13 和 Vite 3.2 的 benchmark 來驗證自己的主張。程式碼和方法在此處開源。

我的方法的要點是通過測量以下兩個時間戳之間的增量來比較 HMR 效能:

  • 修改原始檔的時間,通過單獨的 node.js 程序來觀測檔案更改;

  • 重新渲染更新的 React 元件的時間,通過直接在元件的 render 函數呼叫Date.now()來記錄。請注意,此呼叫發生在元件的虛擬 DOM render 階段,因此不會受到 React reconciliation 或實際 DOM 更新的影響。

benchmark 還測量了兩種不同情況下的數位:

  • 「根」案例,該元件會匯入 1,000 個不同的 child 元件,並且一起渲染。

  • 「葉子」案例,該元件是由根匯入,但自身沒有子元件。

差別

在聊數位之前,有幾個額外的差異值得一提:

  • Next 是否使用 React Server Component(RSC)。

  • Vite 是否使用 SWC 來替代 Babel 進行 React 跳脫。

React Server Components

Next 13 引入了一個主要的架構轉變,因為現在元件預設為伺服器元件,除非使用者使用「use-client」指令明確選擇使用者端模式。不僅是預設設定,Next 檔案還建議使用者儘可能保持伺服器元件模式,以提高終端使用者的效能。

我的初始 benchmark 測試測了 Next 13 在伺服器模式下的根元件和葉元件的 HMR 效能。結果表明,在這兩種情況下,Next 13 的速度實際上都較慢,並且葉元件的差異顯著。

Round 1 snapshot (Next w/ RSC, Vite w/ Babel)

當我在 Twitter 上釋出這些數位時,很快就有人指出,我應該在沒有 RSC 的情況下對 Next 元件進行 benchmark 測試,以使其相等。所以我在 Next 根元件中新增了「useclient」指令,以選擇進入使用者端模式。事實上,在使用者端模式下,Next HMR 顯著提高,比 Vite 快 2 倍:

Round 2 snapshot (Next w/o RSC, Vite w/ Babel)

SWC vs. Babel Transforms

我們的目標是使 benchmark 只關注 HMR 效能差異。為了確保我們確實在比較同一個東西,我們還應該消除另一個變數:Vite 的預設 React preset 使用 Babel 來轉換 React HMR 和 JSX。

React HMR 和 JSX 轉換不是與構建工具耦合的特性。可以通過 Babel(基於 js)或 SWC(基於 rust)完成。Esbuild 也可以轉換 JSX,但缺少對 HMR 的支援。SWC 明顯快於 Babel(單執行緒下 20 倍,多核心下 70 倍)。Vite 目前預設為 Babel 的原因是在安裝大小和實用性之間進行權衡。SWC 的安裝容量相當大(node_modules 中佔用 58MB,而 Vite 本身才 19MB),許多使用者仍然依賴 Babel 進行其他轉換,因此 Babel pass 對他們來說是不可避免的。當然,這在未來可能會改變。

Vite core 不依賴 Babel。只需要用 vite-plugin-swc-react-refresh 來替換預設的 React 外掛即可。切換後,我們看到了根案例中 Vite 的顯著改進,超過了 Next:

有趣的是,這裡的成長曲線顯示,Next/turbo 在根情況下比葉情況下慢 4 倍,而 Vite 只慢 2.4 倍。這意味著 Vite HMR 在更大型的元件中表現更好。

此外,切換到 SWC 也應改善 Vercel benchmark 測試中 Vite 的冷啟動指標。

在不同的硬體上的效能

因為這是一個涉及 Node.js 和和原生 Rust 部分的複合測試,在不同的硬體上會有非凡的差異。我釋出的結果是在我的 M1 MacBook Pro 上收集的。其他使用者在不同的硬體上執行了相同的 benchmark 測試,並報告了不同的結果。

在某些情況下,根案例下的 Vite 更快。

而在另外一些情況下,兩種情況下 Vite 都明顯更快。

Vercel 的澄清

在我釋出了我的 benchmark 之後,Vercel 釋出了一篇博文,澄清了他們的 benchmark 方法,並將其 benchmark 提供給公眾驗證。雖然這可能是第一天就做的事兒,但這絕對是朝著正確方向邁出的一步。

讀完貼文和 benchmark 程式碼後,這裡有幾個關鍵要點:

  • Vite 實現仍然使用預設的基於 Babel 的 React 外掛。

  • 1k 元件的案例下有數位的四捨五入問題,Turbopack 的 15ms 被舍入城 0.01s,Vite 的 87ms 被舍入城 0.09s。這把本來接近 6 倍的差距擴大到了 10 倍。

  • Vercel 的 benchmark 使用更新模組的「瀏覽器 eval 時間」作為結束時間戳,而不是 React 元件重新渲染時間。

  • 該貼文包括一張圖表,顯示當模組總數超過 30k 時,Turbopack 可以比 Vite 快 10 倍。

總結下來,「比 Vite 快 10 倍」必須在以下條件下才成立:

  • Vite 未使用相同的 SWC 轉換。

  • 該應用程式包含超過30k個模組

  • Benchmark 只測量熱更新模組被評估的時間,而不是實際應用更改的時間。

什麼是「公平」比較?

由於 Vercel 的 benchmark 測試測量「模組評估時間」,以排除 React 的 HMR 執行時引起的差異,我們可以假設 benchmark 測試的目標是對 Vite 和 Turbopack 固有的 HMR 機制進行公正的比較。

不幸的是,在這個前提下,Vite 仍然在 benchmark 測試中使用 Babel,這並不平等,這讓 10 倍速度的宣告無效了。在使用 SWC 轉換的 Vite 來矯正數位之前,應將其視為不準確的測試。

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

  • 對於絕大多數使用者來說,30k 模組數量是一個極不可能的場景。隨著 Vite 使用 SWC,達到 10 倍要求所需的模組數量可能會變得更加不切實際。雖然這在理論上是可能的,但用它來證明 Vercel 一直行銷的成績,是很虛偽的。

  • 使用者更關心端到端的 HMR 效能,即從儲存到看到反映的更改的時間,而不是理論上的「模組評估」時間。當看到「更新速度快 10 倍」時,一般使用者會考慮前者而不是後者。Vercel 在其行銷中圖方便省略了這一警告。實際上,Next 中伺服器元件的端到端 HMR(預設值)比 Vite 中的

作為 Vite 的作者,我很高興看到像 Vercel 這樣資金雄厚的公司在改進前端工具方面進行了大量投資。如果適用,我們甚至可以在未來在 Vite 中利用 Turbopack。我相信 OSS 領域的健康競爭最終會讓所有開發者受益。

然而,我也認為開放原始碼軟體的競爭應該建立在公開溝通、公平比較和相互尊重的基礎上。令人失望和擔憂的是,看到激進的行銷使用了精心挑選的、未經同行評審的、邊緣誤導性的數位,這些數位通常只在商業競爭中出現。作為一家建立在 OSS 成功之上的公司,我相信 Vercel 可以做得更好。

(學習視訊分享:)

以上就是尤雨溪迴應:Vite 真的比 Turbopack 慢 10 倍嗎?的詳細內容,更多請關注TW511.COM其它相關文章!