Back返回部落格

Next.js 12

Next.js 12 推出了全新的 Rust 編譯器、中介軟體 (beta)、React 18 支援、原生 ESM 支援、URL 導入、React 伺服器元件 (alpha) 等眾多新功能!

正如我們在 Next.js Conf 上所宣布的,Next.js 12 是我們有史以來最重大的版本更新:

立即執行 npm i next@latest 進行更新。

使用 Rust 編譯器加速建置與 Fast Refresh

我們希望讓每個 Next.js 應用程式在生產環境中建置得更快,並在本地開發時獲得即時反饋。Next.js 12 包含了一個全新的 Rust 編譯器,它利用了原生編譯的優勢。

我們的 Rust 編譯器基於 SWC 構建,這是一個面向下一代快速工具的開放平台。我們優化了打包和編譯過程,本地開發的 Fast Refresh 速度提升約 3 倍,生產環境建置速度提升約 5 倍。其他改進和功能包括:

使用新的 Rust 編譯器處理大型 Next.js 程式碼庫的結果。

使用新的 Rust 編譯器處理大型 Next.js 程式碼庫的結果。

  • 針對大型程式碼庫的進一步速度提升:我們已經用世界上一些最大的 Next.js 程式碼庫驗證了 Rust 編譯器。
  • 改進效能可觀測性:Next.js 現在會在控制台輸出 Fast Refresh 的時間,包含客戶端和伺服器端的編譯時間,以及編譯的模組和檔案數量。
  • 底層 webpack 改進:我們對 webpack 進行了多項改進,包括優化 Fast Refresh 和提高按需載入的可靠性。

使用 Rust 進行編譯比 Babel 快 17 倍,並且在 Next.js 12 中預設啟用,取代了 JavaScript 和 TypeScript 檔案的轉換。這意味著我們必須將 Next.js 中的 Babel 轉換移植到 Rust,包括用於實現 styled-jsx 轉換的 全新 Rust CSS 解析器

新的 Rust 編譯器向後兼容。如果您有現有的 Babel 配置,將自動選擇退出。我們計劃很快移植對流行函式庫(如 styled-componentsemotionrelay)的解析支援。如果您使用自訂的 Babel 設定,請分享您的配置

您也可以選擇使用 Rust 編譯器進行程式碼壓縮。這比 Terser 快 7 倍。程式碼壓縮功能目前是選擇性啟用,直到經過全面驗證,因為它取代了多年來的基礎設施。

next.config.js
module.exports = {
  swcMinify: true,
};

除了聘請 SWC 的創始人 DongYoon KangParcel 的貢獻者 Maia Teegarden 之外,我們還將繼續投資 Rust 生態系統。如果您有 Rust 相關經驗,請申請加入我們的團隊

更多資訊,請觀看我們在 Next.js Conf 上的演示影片

中介軟體介紹

中介軟體讓您能夠以程式碼優先的方式進行配置。這為 Next.js 提供了完整的靈活性,因為您可以在請求完成之前執行程式碼。根據使用者的傳入請求,您可以通過重寫、重定向、添加標頭甚至串流 HTML 來修改回應。

中介軟體讓您在 Next.js 中擁有完全的靈活性。

中介軟體讓您在 Next.js 中擁有完全的靈活性。

中介軟體可用於任何需要在一組頁面之間共享邏輯的情況,包括:

中介軟體使用一個嚴格的運行時環境,支援標準的 Web API,如 fetch。這在使用 next start 時開箱即用,同時也適用於像 Vercel 這樣的邊緣平台,這些平台使用 Edge Middleware

要在 Next.js 中使用中介軟體,您可以創建一個檔案 pages/_middleware.js。在這個例子中,我們使用了標準的 Web API Response (MDN):

pages/_middleware.js
export function middleware(req, ev) {
  return new Response('Hello, world!');
}

更多資訊,請觀看我們在 Next.js Conf 上的演示影片查閱文件

為 React 18 做準備

React 18 將增加 Suspense、自動批次更新、startTransition 等 API,以及一個新的伺服器渲染串流 API,支援 React.lazy

我們一直與 Facebook 的 React 團隊密切合作,為 React 18 的穩定版發布做準備。我們在 Next.js 12 中通過實驗性標誌提供了這些功能供您試用。

Terminal
npm install react@alpha react-dom@alpha

伺服器端串流

React 18 中的並發功能包括對伺服器端 Suspense 和 SSR 串流的內建支援。這允許您使用 HTTP 串流來伺服器渲染頁面。這是 Next.js 12 中的一個實驗性功能,但一旦啟用,SSR 將使用與中介軟體相同的嚴格運行時環境。

要啟用此功能,請使用實驗性標誌 concurrentFeatures: true

next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
  },
};

React 伺服器元件 (React Server Components)

React 伺服器元件讓我們能夠在伺服器端渲染所有內容,包括元件本身。這與伺服器端渲染 (SSR) 有根本上的不同,後者僅在伺服器預先生成 HTML。使用伺服器元件時,完全不需要客戶端 JavaScript,使頁面渲染速度更快。這能提升應用程式的使用者體驗,同時結合伺服器渲染的最佳部分與客戶端互動性。

next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
    serverComponents: true,
  },
};

Next.js 現在允許您在_元件層級_進行資料獲取,全部以 JSX 表達。透過使用 React 伺服器元件,我們可以簡化流程。不再需要特殊函式如 getServerSidePropsgetStaticProps,這與 React Hooks 將資料獲取與元件放在一起的模型一致。

您可以將任何 Next.js 頁面重新命名為 .server.js 來建立伺服器元件,並直接在伺服器元件中導入客戶端元件。這些客戶端元件將會水合 (hydrate) 並變得可互動,因此您可以添加如「按讚」等功能。

我們目前正在 Next.js 中開發伺服器端的 Suspense、選擇性水合 (selective hydration) 和串流渲染 (streaming rendering),並將在未來的部落格文章中分享進展。

特別感謝我們的合作者 Kara EricksonGerald Monaco 來自 Google Aurora 團隊,他們在 React 18 和伺服器元件上的貢獻。

更多資訊,請觀看我們在 Next.js Conf 的示範查看文件

ES 模組支援與 URL 導入 (ES Modules Support and URL Imports)

ES 模組為 JavaScript 帶來了官方標準化的模組系統,所有主流瀏覽器和 Node.js 都支援此標準。

此標準透過實現更小的套件體積和 JavaScript 打包檔案推動了網頁生態系統的進步,最終帶來更好的使用者體驗。隨著 JavaScript 生態系統從 Common JS(舊標準)過渡到 ES 模組,我們致力於幫助開發者逐步採用這些改進,而無需不必要的破壞性變更。

Next.js 11.1 開始,我們添加了對 ES 模組的實驗性支援,並優先於 CommonJS 模組。在 Next.js 12 中,這已成為預設行為。導入僅提供 CommonJS 的 NPM 模組仍然受到支援。

URL 導入 (URL Imports)

Next.js 12 包含實驗性支援,可透過 URL 導入 ES 模組,無需安裝或單獨的建置步驟。

URL 導入允許您直接透過 URL 使用_任何_套件。這使 Next.js 能夠像處理本地依賴項一樣處理遠端 HTTP(S) 資源。

如果檢測到 URL 導入,Next.js 將生成一個 next.lock 檔案來追蹤遠端資源。URL 導入會在本機快取,以確保您仍可在離線狀態下工作。Next.js 支援客戶端和伺服器端的 URL 導入。

若要啟用此功能,請在 next.config.js 中添加允許的 URL 前綴:

next.config.js
module.exports = {
  experimental: {
    urlImports: ['https://cdn.skypack.dev'],
  },
};

然後,您可以直接從 URL 導入模組:

import confetti from 'https://cdn.skypack.dev/canvas-confetti';

任何提供 ES 模組的 CDN 都可以使用,包括無代碼和設計工具如 Framer:

更多資訊,請觀看我們在 Next.js Conf 的示範查看文件

針對爬蟲的 ISR 後備方案 (Bot-Aware ISR Fallback)

目前,增量靜態再生 (Incremental Static Regeneration) 搭配 fallback: true 會在首次請求尚未生成的頁面時,先渲染後備狀態 (fallback state) 再顯示頁面內容。若要阻止頁面載入(伺服器端渲染),您需要使用 fallback: 'blocking'

在 Next.js 12 中,網路爬蟲(如搜尋引擎機器人) 將自動使用 fallback: true 來伺服器端渲染 ISR 頁面,同時仍向非爬蟲的 User-Agent 提供後備狀態的舊行為。這可防止爬蟲索引載入狀態。

使用 AVIF 實現更小的圖片 (Smaller images using AVIF)

內建的圖片優化 API 現在支援 AVIF 圖片,與 WebP 相比可減少 20% 的圖片大小。

AVIF 圖片的優化時間可能比 WebP 長,因此我們透過 next.config.js 中的新屬性 images.formats 讓此功能可選擇性啟用:

next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
};

此格式列表用於根據請求的 Accept 標頭動態決定優化的圖片格式。由於 AVIF 排在第一位,如果瀏覽器支援 AVIF,則會提供 AVIF 格式。如果不支援,則會檢查是否支援 WebP(瀏覽器支援 WebP)。如果兩種格式都不支援,則會提供原始圖片格式。

輸出檔案追蹤 (Output File Tracing)

在 Next.js 8 中,我們引入了 target 選項。這允許將 Next.js 頁面輸出為獨立的 JavaScript 打包檔案,透過在建置時使用 webpack 打包所有依賴項。我們很快意識到這並非理想方案,轉而建立了 @vercel/nft@vercel/nft 已在 Vercel 平台上的所有部署中使用超過 2 年。

現在,我們將這些改進直接帶入 Next.js 框架並設為預設,適用於所有部署平台,提供了比 target 選項顯著更好的方案。

Next.js 12 會自動使用 @vercel/nft 追蹤每個頁面和 API 路由所需的檔案,並將追蹤結果輸出到 next build 的輸出旁邊,讓整合者能夠利用 Next.js 自動提供的追蹤資訊。

這些變更也優化了使用 Docker 等工具透過 next start 部署的應用程式。透過利用 @vercel/nft,我們未來將能夠使 Next.js 輸出完全獨立。執行應用程式時無需安裝任何依賴項,大幅減少 Docker 映像大小。

@vercel/nft 引入 Next.js 取代了 target 方案,因此在 Next.js 12 中 target 已被棄用。查看文件以獲取更多資訊。

其他改進 (Other Improvements)

  • 現在,添加 pages/_app.jspages/_document.js 到您的應用程式會自動替換內建版本,無需重新啟動 Next.js CLI。
  • ESLint 整合現在支援在 next lint 中使用 --file 標記進行單一檔案檢查
  • Next.js 12 現在支援設定自訂的 tsconfig.json 路徑。
  • 現在支援使用 next.config.mjs 以 ES 模組形式撰寫配置。
  • 現在會對重複的 getStaticProps 飛行中請求 (in-flight requests) 進行去重處理。
  • 現在使用共享的工作池 (worker pool) 來檢查靜態頁面。
  • Fast Refresh 現在使用 WebSocket 連接而非 EventSource 連接。

破壞性變更 (Breaking Changes)

  • Next.js 11 中將 webpack 5 設為預設後,我們現在正式移除了 webpack 4。我們與社群密切合作,確保順利過渡到 webpack 5。
  • next.config.js 中的 target 不再需要。
  • next/image 現在使用 span 作為包裹元素,而非 div
  • 最低 Node.js 版本已從 12.0.0 提升至 12.22.0,這是首個支援原生 ES 模組的 Node.js 版本。

欲了解更多,請查看升級指南

社群 (Community)

五年前,我們向公眾發布了 Next.js。我們的目標是建立一個零配置的 React 框架,簡化開發者體驗。回顧過去,看到社群的成長以及我們共同實現的成果令人驚嘆。讓我們繼續前進。

Next.js 是超過 1,800 位獨立開發者、Google 和 Facebook 等產業合作夥伴以及我們核心團隊共同努力的成果。

此版本由以下貢獻者共同實現:@ka2n, @housseindjirdeh, @rojserbest, @lobsterkatie, @thibautsabot, @javivelasco, @sokra, @rishabhpoddar, @kdy1, @huozhi, @georgegach, @ionut-botizan, @paul-creates, @TimBarley, @kimizuy, @devknoll, @matamatanot, @christianvuerings, @pgrodrigues, @mohamedbhy, @AlfonzAlfonz, @kara, @molebox, @angelopoole, @oste, @genetschneider, @jantimon, @kyliau, @mxschmitt, @PhattOZ, @finn-orsini, @kriswuollett, @harryheman, @GustavoEdinger, @AryanBeezadhur, @Blevs, @colevscode, @atcastle, @ijjk, @velocity23, @jonowu, @timneutkens, @whitep4nth3r, @micro-chipset, @TyMick, @padmaia, @arthurdenner, @vitorbal, @zNeb, @jacksonhardaker, @shuding, @kylemh, @Bundy-Mundi, @ctjlewis, @thien-do, @leerob, @Dev-CasperTheGhost, @janicklas-ralph, @rezathematic, @KonstHardy, @fracture91, @lorensr, @Sheraff, @HaNdTriX, @emilio, @oluan, @ddzieduch, @colinclerk, @x4th, @volcareso, @oiva, @sinchang, @scottrepreneur, @smakosh, @catnose99, @adrienharnay, @donsn, @andersonleite, @msp5382, @tim-hanssen, @appsplash99, @alexvilchis, @RobEasthope, @royal, @Perry-Olsson, @well-balanced, @mrmckeb, @buraksakalli, @espipj, @prateekbh, @AleksaC, @eungyeole, 和 @rgabs