學(xué)不動了,Vercel 推出比 Vite 快 10 倍的打包器 Turbopack
介紹
Vercel 是由 Guillermo Rauch 創(chuàng)立的云服務(wù)公司,前身為 Zeit,有 Next.js、Node.js 的 websocket 框架 socket.io 和 MongoDB 客戶端 mongoose 等知名開源項目為大眾所知。Next.js 為了實現(xiàn)后端渲染,重度使用了 JS 生態(tài)中的打包構(gòu)建工具 webpack。
這兩天,Vercel 的團隊宣布推出了 Next.js 13,該版本的一些亮點更新內(nèi)容包括:
-
**Directory (beta):**[1] 更簡單、更快、更少的客戶端 JS。
- **Layouts** [2]
- **React Server Components** [3]
- **Streaming** [4]
-
Turbopack (alpha):[5] 速度提高 700 倍的基于 Rust 的 Webpack 替代品。
-
新的 `next/image` (stable)[6] :[7] native browser 延遲加載速度更快。
-
新的 `@next/font`[8] (beta)[9] :[10] 具有零布局偏移的自動自托管字體。
-
改進 `next/link`:[11] Simplified API with automatic
<a>。
更新:
npm?i?next@latest?react@latest?react-dom@latest?eslint-config-next@latest
Directory (beta) [12]
通過引入 app/directory 來改進 Next.js 中的路由和布局,這是之前為征求社區(qū)反饋而發(fā)布的 Layouts RFC 的結(jié)果。[13]包括對以下內(nèi)容的支持:
- Layouts:[14] 輕松共享 UI,同時保留狀態(tài)并避免重新渲染。
- Server Components:[15] 使服務(wù)器優(yōu)先成為大多數(shù)動態(tài)應(yīng)用程序的默認(rèn)設(shè)置。
- Streaming:[16] 顯示即時加載狀態(tài)并流式傳輸更新。
-
Suspense for Data Fetching[17] :[18] 新的
usehook 支持 component-level fetching。
該 app/directory 可以與現(xiàn)有 pages directory 共存以進行 incremental adoption。公告指出,雖然在升級到 Next.js 13 時不需要使用該 app/directory,但其正在為構(gòu)建復(fù)雜的 interfaces 奠定基礎(chǔ),同時減少 JavaScript 的數(shù)量。

引入 Turbopack (alpha) [19]
Next.js 13 中包含 Turbopack[20] —— Webpack 的新的基于 Rust 的繼任者,針對 JavaScript 和 TypeScript 優(yōu)化的增量打包器。
“Webpack 已被下載超過 30 億次。雖然它是構(gòu)建 Web 不可或缺的一部分,但我們已經(jīng)達(dá)到了基于 JavaScript 的工具所能達(dá)到的最大性能的極限。在 Next.js 12 中,我們開始過渡到 native Rust 驅(qū)動的工具。我們首先從 Babel 遷移,這導(dǎo)致轉(zhuǎn)譯速度提高了 17 倍。然后,我們替換了 Terser,這使得 minification 提高了 6 倍?,F(xiàn)在是時候全身心投入到原生的打包工作中去了?!?/p>
將 Turbopack (alpha) 與 Next.js 13 一起使用可以:
- 更新速度比 Webpack 快 700 倍
- 更新速度比 Vite 快 10 倍
- cold starts(冷啟動)速度比 Webpack 快 4 倍

根據(jù)介紹,Turbopack 只打包開發(fā)中所需要的最小資產(chǎn),所以啟動時間非???。在一個有 3000 個模塊的應(yīng)用程序中,Turbopack 的啟動時間為 1.8 秒。Vite 需要 11.4 秒,Webpack 需要 16.5 秒。
Turbopack 對服務(wù)器組件、TypeScript、JSX、CSS 等提供了開箱即用的支持。不過在 Alpha 版期間,許多功能[21]尚不受支持。
“注意: Next.js 中的 Turbopack 目前僅支持
”next dev,可查看支持的功能[22]。開發(fā)團隊還在努力通過 Turbopack 添加next build支持。未來我們將發(fā)布獨立的 CLI、插件 API,并支持其他框架,如 Svelte 和 Vue。
可在 Next.js 13 中通過 next dev --turbo 試用 Turbopack (alpha)。
打包與原生 ESM
像 Vite 這樣的框架使用了一種技術(shù),它們不會在開發(fā)模式下打包應(yīng)用程序源代碼。相反,它們依賴于瀏覽器的原生 ES Modules 系統(tǒng)。這種方法會導(dǎo)致令人難以置信的響應(yīng)更新,因為它們只需要轉(zhuǎn)換單個文件。
但是,Vite 可能會遇到由許多模塊組成的大型應(yīng)用程序的擴展問題。瀏覽器中的大量級聯(lián)網(wǎng)絡(luò)請求會導(dǎo)致啟動時間相對較慢。對于瀏覽器來說,如果它可以在盡可能少的網(wǎng)絡(luò)請求中接收到它需要的代碼——即使是在本地服務(wù)器上,它會更快。
這就是為什么我們決定像 Webpack 一樣,希望 Turbopack 將代碼打包在開發(fā)服務(wù)器中。Turbopack 可以更快地完成它,尤其是對于大型應(yīng)用程序,因為它是用 Rust 編寫的,并且跳過了僅在生產(chǎn)環(huán)境中需要的優(yōu)化工作。
增量計算
我們的團隊吸取了 Webpack 10 年的經(jīng)驗教訓(xùn),結(jié)合了Turborepo[23] 和 Google 的 Bazel 在增量計算方面的創(chuàng)新,并創(chuàng)建了一個可以支持未來幾十年計算的架構(gòu)。
有兩種方法可以加快進程:減少工作量或并行工作。我們知道,如果我們想讓最快的打包器成為可能,我們需要用力拉動兩個杠桿。
我們決定為分布式和增量行為創(chuàng)建一個可重用的 Turbo 構(gòu)建引擎。Turbo 引擎就像函數(shù)調(diào)用的調(diào)度程序一樣工作,允許在所有可用內(nèi)核上并行調(diào)用函數(shù)。
Turbo 引擎還緩存它調(diào)度的所有函數(shù)的結(jié)果,這意味著它永遠(yuǎn)不需要兩次執(zhí)行相同的工作。簡而言之,它以最大速度做最少的工作。
Vite 和 esbuild
其他工具對“做更少的工作”采取不同的態(tài)度。Vite 通過在開發(fā)模式下使用 Native ESM 將工作量降至最低。出于上述原因,我們決定不采用這種方法。
在底層,Vite 將 esbuild 用于許多任務(wù)。esbuild 是一個打包器 - 一個非??斓?。它不會強迫您使用本機 ESM。但出于幾個原因,我們決定不采用 esbuild。
esbuild 的代碼針對一項任務(wù)進行了超優(yōu)化 - 快速打包。它沒有 HMR,我們不想從我們的開發(fā)服務(wù)器中丟失它。
esbuild 是一個非??焖俚拇虬ぞ撸]有做太多的緩存。這意味著你最終_會_一次又一次地做同樣的工作,即使這項工作是以本機的速度進行的。
Evan Wallace 將 esbuild 稱為下一代打包器的概念驗證[24]。我們認(rèn)為他是對的。我們認(rèn)為具有增量計算的 Rust 驅(qū)動的打包器在更大的規(guī)模上可以比 esbuild 更好地執(zhí)行。
懶惰打包
Next.js 的早期版本試圖在開發(fā)模式下打包整個Web 應(yīng)用程序。我們很快意識到這種“急切”的方法并不是最優(yōu)的。Next.js 的現(xiàn)代版本僅打包開發(fā)服務(wù)器請求的頁面。例如,如果您轉(zhuǎn)到 localhost:3000,它將僅打包 pages/index.jsx,以及它導(dǎo)入的模塊。
這種更“懶惰”的方法(僅在絕對必要時打包資產(chǎn))是快速開發(fā)服務(wù)器的關(guān)鍵。本機 ESM 無需太多魔法即可處理此問題 - 您請求一個模塊,該模塊又請求其他模塊。但是,出于上述原因,我們想構(gòu)建一個打包器。
esbuild 沒有“惰性”打包的概念——除非您專門針對某些入口點,否則它是全有或全無的。
Turbopack 的開發(fā)模式會根據(jù)收到的請求構(gòu)建應(yīng)用程序?qū)牒蛯?dǎo)出的最小圖,并且僅打包必要的最少代碼。在核心概念文檔[25]中了解更多信息。
這種策略使 Turbopack 在第一次啟動開發(fā)服務(wù)器時變得非常快。我們只計算渲染頁面所需的代碼,然后將其以單個塊的形式發(fā)送到瀏覽器。在大規(guī)模情況下,這最終比原生 ESM 快得多。
我們想要:
- 構(gòu)建一個打包器。在處理大型應(yīng)用程序時,打包程序的性能優(yōu)于本機 ESM。
- 使用增量計算。Turbo 引擎將這一點帶入 Turbopack 架構(gòu)的核心——最大化速度并最小化完成的工作。
- 優(yōu)化我們的開發(fā)服務(wù)器的啟動時間。為此,我們構(gòu)建了一個惰性資產(chǎn)圖來僅計算請求的資產(chǎn)。
這就是我們選擇構(gòu)建 Turbopack 的原因。
更多詳情可查看官方公告[26]。
值得一提的是,Turbopack 還是出自 Webpack 作者 TobiasKoppers 之手。值得一提的是,Turbopack 還是出自 ?Webpack作者 ?Tobias Koppers之手。Tobias Koppers 于 2021 年 4 月加入 Vercel,參與了 Turbopack 的開發(fā)。
關(guān)于 Turbopack 的由來,Vercel 首席執(zhí)行官 Guillermo Rauch 透露[27],Next.js 早在 2016 年就開始使用 Webpack 作為一個組件?!拔覀兛赡苁?Webpack 的最大用戶。我們開始和作者聊了很多,因為當(dāng)時我們有像沃爾瑪這樣的客戶,有超過 250 名工程師在 Next.js 代碼庫上工作,分享關(guān)于編譯過程的反饋。我們意識到 JavaScript 和 TypeScript 代碼的數(shù)量增長如此之快,以至于超出了基于 JavaScript 的工具和架構(gòu)的能力。Tobias 從未想過該工具會得到如此廣泛的采用?!?/p>
另一個因素是 Webpack 面向單頁應(yīng)用程序 (SPA) 的方向?!癧2016 年] 每個人都在構(gòu)建單頁應(yīng)用程序。我們對市場說不,我們將進行服務(wù)器渲染并編排由多個入口點組成的復(fù)雜應(yīng)用程序,因此我們開始改變 Webpack 的默認(rèn)設(shè)置。Webpack 非常單一且面向 SPA?!?/p>
當(dāng) Tobias 加入 Vercel 時,“他帶來了 10 年的專業(yè)知識,見證了這件事情的發(fā)展。但他意識到架構(gòu)和運行時的所有缺陷。因此,Tobias 成為了 Rust 專家?!?/p>
此外,Vercel 首席技術(shù)官 Malte Ubl 還表示,Turbopack 旨在成為 Webpack 的直接替代品,Next.js 則是它的第一個客戶。 “隨著時間的推移,我們計劃針對所有開發(fā)者用例繼續(xù)迭代和改進 Turbopack。它是開源的,我們期待看到社區(qū)如何參與該工具的早期階段。”
在被問及如何看待 Webpack 的未來,以及是否預(yù)計在更廣泛的網(wǎng)絡(luò)社區(qū)中,大量的 Webpack 使用會遷移到 Turbopack 這一問題時?
Tobias 的回答是,“現(xiàn)在是整個網(wǎng)絡(luò)生態(tài)系統(tǒng)的編譯器基礎(chǔ)架構(gòu)的一個新起點。Webpack 已被下載超過 30 億次。它已成為 Web 構(gòu)建不可或缺的一部分。但就像 Babel 和 Terser 一樣,現(xiàn)在是 all-in on native 的時候了。我加入了 Vercel,組建了一個團隊來構(gòu)建網(wǎng)絡(luò)的下一代 bundler?!?/p>
他還補充稱,預(yù)計 Webpack 不會很快從 Next.js 中消失。向后兼容性是 Next.js 不可或缺的一部分,他們將關(guān)心所有使用自定義插件的 Next.js 用戶。Webpack 將在 Next.js 中保持足夠長的活躍時間,但同時其團隊還將繼續(xù)改進 Turbopack,從而實現(xiàn)最終在 Next.js 中完全取代 Webpack。
“本文經(jīng)作者 zkj 授權(quán)轉(zhuǎn)發(fā),原文鏈接:https://juejin.cn/post/7158791870796169230,
”
參考資料
[1]https://nextjs.org/blog/next-13#app-directory-beta: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23app-directory-beta
[2]https://nextjs.org/blog/next-13#layouts: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23layouts
[3]https://nextjs.org/blog/next-13#server-components: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23server-components
[4]https://nextjs.org/blog/next-13#streaming: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23streaming
[5]https://nextjs.org/blog/next-13#introducing-turbopack-alpha: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23introducing-turbopack-alpha
[6]https://nextjs.org/blog/next-13#nextimage: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23nextimage
[7]https://nextjs.org/blog/next-13#nextimage: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23nextimage
[8]https://nextjs.org/blog/next-13#nextfont: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23nextfont
[9]https://nextjs.org/blog/next-13#nextfont: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23nextfont
[10]https://nextjs.org/blog/next-13#nextfont: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23nextfont
[11]https://nextjs.org/blog/next-13#breaking-changes: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23breaking-changes
[12]https://nextjs.org/blog/next-13#app-directory-beta: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23app-directory-beta
[13]https://nextjs.org/blog/layouts-rfc: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Flayouts-rfc
[14]https://nextjs.org/blog/next-13#layouts: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23layouts
[15]https://nextjs.org/blog/next-13#server-components: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23server-components
[16]https://nextjs.org/blog/next-13#streaming: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23streaming
[17]https://nextjs.org/blog/next-13#data-fetching: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23data-fetching
[18]https://nextjs.org/blog/next-13#data-fetching: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23data-fetching
[19]https://nextjs.org/blog/next-13#introducing-turbopack-alpha: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13%23introducing-turbopack-alpha
[20]https://vercel.com/blog/turbopack: https://link.juejin.cn/?target=https%3A%2F%2Fvercel.com%2Fblog%2Fturbopack
[21]https://turbo.build/pack/docs/features: https://link.juejin.cn/?target=https%3A%2F%2Fturbo.build%2Fpack%2Fdocs%2Ffeatures
[22]https://turbo.build/pack/docs/features: https://link.juejin.cn/?target=https%3A%2F%2Fturbo.build%2Fpack%2Fdocs%2Ffeatures
[23]https://turbo.build/repo: https://link.juejin.cn/?target=https%3A%2F%2Fturbo.build%2Frepo
[24]https://news.ycombinator.com/item?id=22336334: https://link.juejin.cn/?target=https%3A%2F%2Fnews.ycombinator.com%2Fitem%3Fid%3D22336334
[25]https://turbo.build/pack/docs/core-concepts: https://link.juejin.cn/?target=https%3A%2F%2Fturbo.build%2Fpack%2Fdocs%2Fcore-concepts
[26]https://nextjs.org/blog/next-13: https://link.juejin.cn/?target=https%3A%2F%2Fnextjs.org%2Fblog%2Fnext-13
[27]https://devclass.com/2022/10/25/webpack-founder-debuts-rust-based-turbopack-that-is-700x-faster/: https://link.juejin.cn/?target=https%3A%2F%2Fdevclass.com%2F2022%2F10%2F25%2Fwebpack-founder-debuts-rust-based-turbopack-that-is-700x-faster%2F
