原文: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 的效能。 【相關推薦:vuejs影片教學、web前端開發】
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 轉義。
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)
#我們的目標是讓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 都明显更快。
在我发布了我的 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 倍嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!