Back返回部落格

Next.js 15 候選版本 (RC)

Next.js 15 候選版本 (Release Candidate) 現已發布。這個早期版本讓您能在穩定版發布前測試最新功能。

Next.js 15 候選版本 (Release Candidate) 現已發布。這個早期版本讓您能在穩定版發布前測試最新功能。

立即試用 Next.js 15 RC:

Terminal
npm install next@rc react@rc react-dom@rc

React 19 RC 支援

Next.js App Router 是基於 React canary 頻道為框架構建的,這讓開發者能在 v19 發布前使用這些新 React API 並提供回饋。

Next.js 15 RC 現在支援 React 19 RC,其中包含客戶端和伺服器的新功能,例如 Actions。

閱讀 Next.js 15 升級指南React 19 升級指南,並觀看 React Conf 主題演講以了解更多。

注意: 部分第三方函式庫可能尚未相容 React 19。

React 編譯器 (實驗性功能)

React 編譯器 是由 Meta 的 React 團隊創建的新實驗性編譯器。該編譯器透過對純 JavaScript 語義和 React 規則的深入理解,能在深層次上理解您的程式碼,從而為程式碼添加自動優化。編譯器減少了開發者需手動進行的記憶化操作(如使用 useMemouseCallback API),使程式碼更簡單、更易維護且更不易出錯。

Next.js 15 新增了對 React 編譯器 的支援。

安裝 babel-plugin-react-compiler

Terminal
npm install babel-plugin-react-compiler

然後,在 next.config.js 中添加 experimental.reactCompiler 選項:

next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
module.exports = nextConfig;

您也可以選擇將編譯器配置為「選擇加入」模式:

next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: {
      compilationMode: 'annotation',
    },
  },
};
 
module.exports = nextConfig;

注意: React 編譯器目前只能透過 Babel 插件在 Next.js 中使用,這可能會導致建置時間變長。

了解更多關於 React 編譯器可用的 Next.js 配置選項

水合錯誤改進

Next.js 14.1 改進了 錯誤訊息和水合錯誤。Next.js 15 在此基礎上進一步改進,新增了更完善的水合錯誤視圖。水合錯誤現在會顯示錯誤的原始碼,並提供解決問題的建議。

例如,這是 Next.js 14.1 中先前的水合錯誤訊息:

Next.js 14.1 中的水合錯誤訊息

Next.js 15 RC 已將其改進為:

Next.js 15 RC 中改進的水合錯誤訊息

快取更新

Next.js App Router 推出時採用了預設的快取策略。這些策略旨在提供最高性能的預設選項,同時允許在需要時選擇退出。

根據您的回饋,我們重新評估了快取啟發式方法及其與部分預渲染 (PPR) 等專案和使用 fetch 的第三方函式庫的互動方式。

在 Next.js 15 中,我們將 fetch 請求、GET 路由處理器和客戶端路由快取的預設行為從「預設快取」更改為「預設不快取」。如果您想保留之前的行為,可以繼續選擇啟用快取。

我們將在未來幾個月繼續改進 Next.js 的快取功能,並在 Next.js 15 正式版公告中分享更多細節。

fetch 請求預設不再快取

Next.js 使用 Web fetch APIcache 選項來配置伺服器端 fetch 請求如何與框架的持久 HTTP 快取互動:

fetch('https://...', { cache: 'force-cache' | 'no-store' });
  • no-store - 每次請求都從遠端伺服器獲取資源,且不更新快取
  • force-cache - 從快取(如果存在)或遠端伺服器獲取資源並更新快取

在 Next.js 14 中,如果未提供 cache 選項,則預設使用 force-cache,除非使用了動態函式或動態配置選項。

在 Next.js 15 中,如果未提供 cache 選項,則預設使用 no-store。這意味著 fetch 請求預設不會被快取

您仍可以透過以下方式選擇快取 fetch 請求:

GET 路由處理器預設不再快取

在 Next.js 14 中,使用 GET HTTP 方法的路由處理器預設會被快取,除非它們使用了動態函式或動態配置選項。在 Next.js 15 中,GET 函式 預設不會被快取

您仍可以使用靜態路由配置選項(如 export dynamic = 'force-static')選擇啟用快取。

特殊路由處理器如 sitemap.tsopengraph-image.tsxicon.tsx,以及其他元數據文件,預設仍為靜態,除非它們使用動態函式或動態配置選項。

客戶端路由快取預設不再快取頁面元件

在 Next.js 14.2.0 中,我們引入了一個實驗性的 staleTimes 標誌,允許自訂配置 路由快取 (Router Cache)

在 Next.js 15 中,此標誌仍然可用,但我們將預設行為更改為頁面區段 (Page segments) 的 staleTime 設為 0。這意味著當您在應用程式中導航時,客戶端將始終反映從成為導航一部分的頁面元件 (Page component) 中取得的最新資料。然而,仍有以下重要行為保持不變:

  • 共享佈局資料不會從伺服器重新獲取,以繼續支援 部分渲染 (Partial Rendering)
  • 前進/後退導航仍會從快取中恢復,以確保瀏覽器可以恢復滾動位置。
  • Loading.js 將保持快取 5 分鐘(或 staleTimes.static 配置的值)。

您可以通過以下配置選擇啟用先前的客戶端路由快取行為:

next.config.ts
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
    },
  },
};
 
module.exports = nextConfig;

逐步採用部分預渲染 (Partial Prerendering)(實驗性)

在 Next.js 14 中,我們 引入了部分預渲染 (PPR) —— 一種在相同頁面上結合 靜態和動態渲染 的優化技術。

目前,Next.js 預設使用靜態渲染,除非您使用動態函數 (dynamic functions) 如 cookies()headers() 和未快取的資料請求。這些 API 會將整個路由切換為動態渲染。使用 PPR 時,您可以將任何動態 UI 包裹在 Suspense 邊界中。當新請求進入時,Next.js 會立即提供靜態 HTML 外殼,然後在同一個 HTTP 請求中渲染並串流動態部分。

為了實現逐步採用,我們新增了一個 experimental_ppr 路由配置選項,用於為特定佈局 (Layouts) 和頁面 (Pages) 啟用 PPR:

app/page.jsx
import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
 
export const experimental_ppr = true
 
export default function Page() {
  return {
     <>
	     <StaticComponent />
	     <Suspense fallback={...}>
		     <DynamicComponent />
	     </Suspense>
     </>
  };
}

要使用此新選項,您需要在 next.config.js 文件中將 experimental.ppr 配置設為 'incremental'

next.config.ts
const nextConfig = {
  experimental: {
    ppr: 'incremental',
  },
};
 
module.exports = nextConfig;

一旦所有區段都啟用了 PPR,您就可以安全地將 ppr 值設為 true,並為整個應用程式和所有未來的路由啟用它。

我們將在 Next.js 15 正式版 (GA) 的部落格文章中分享更多關於 PPR 的路線圖。

了解更多關於 部分預渲染 (Partial Prerendering)

使用 next/after 在響應後執行代碼(實驗性)

在處理用戶請求時,伺服器通常執行與計算響應直接相關的任務。然而,您可能需要執行日誌記錄、分析和其他外部系統同步等任務。

由於這些任務與響應沒有直接關係,用戶不應等待它們完成。將工作推遲到響應用戶後執行會帶來挑戰,因為無伺服器 (serverless) 函數在響應關閉後會立即停止計算。

after() 是一個新的實驗性 API,通過允許您安排工作在響應完成串流後處理來解決此問題,使次要任務可以在不阻塞主要響應的情況下運行。

要使用它,請在 next.config.js 中添加 experimental.after

next.config.ts
const nextConfig = {
  experimental: {
    after: true,
  },
};
 
module.exports = nextConfig;

然後,在伺服器元件 (Server Components)、伺服器操作 (Server Actions)、路由處理器 (Route Handlers) 或中介軟體 (Middleware) 中導入該函數。

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // 次要任務
  after(() => {
    log();
  });
 
  // 主要任務
  return <>{children}</>;
}

了解更多關於 next/after

create-next-app 更新

對於 Next.js 15,我們更新了 create-next-app 的設計。

Next.js 15 RC 中 create-next-app 的新設計

運行 create-next-app 時,會有一個新的提示詢問您是否要為本地開發啟用 Turbopack(預設為 No)。

Terminal
 您是否希望在 next dev 中使用 Turbopack? /

可以使用 --turbo 標誌來啟用 Turbopack。

Terminal
npx create-next-app@rc --turbo

為了讓新專案的入門更加容易,CLI 新增了一個 --empty 標誌。這將移除任何多餘的文件和樣式,生成一個極簡的「hello world」頁面。

Terminal
npx create-next-app@rc --empty

優化外部套件的打包(穩定版)

打包外部套件可以提高應用程式的冷啟動性能。在 App Router 中,外部套件預設會被打包,您可以使用新的 serverExternalPackages 配置選項選擇退出特定套件。

Pages Router 中,外部套件預設不會被打包,但您可以使用現有的 transpilePackages 選項提供要打包的套件列表。使用此配置選項時,您需要指定每個套件。

為了統一 App 和 Pages Router 的配置,我們引入了一個新選項 bundlePagesRouterDependencies,以匹配 App Router 的預設自動打包行為。然後,您可以使用 serverExternalPackages 選擇退出特定套件(如果需要)。

next.config.ts
const nextConfig = {
  // 在 Pages Router 中自動打包外部套件:
  bundlePagesRouterDependencies: true,
  // 為 App 和 Pages Router 選擇退出特定套件的打包:
  serverExternalPackages: ['package-name'],
};
 
module.exports = nextConfig;

了解更多關於 優化外部套件

其他變更

  • [重大變更] 最低 React 版本現在為 19 RC
  • [重大變更] next/image:移除 squoosh,改用 sharp 作為可選依賴項 (PR)
  • [重大變更] next/image:將預設 Content-Disposition 更改為 attachment (PR)
  • [重大變更] next/image:當 src 有前導或尾隨空格時報錯 (PR)
  • [重大變更] 中介軟體 (Middleware):應用 react-server 條件來限制不推薦的 React API 導入 (PR)
  • [重大變更] next/font:移除對外部 @next/font 套件的支援 (PR)
  • [重大變更] next/font:移除 font-family 雜湊 (PR)
  • [重大變更] 快取:force-dynamic 現在會將 no-store 設為 fetch 快取的預設值 (PR)
  • [重大變更] 配置:啟用 swcMinify (PR)、missingSuspenseWithCSRBailout (PR) 和 outputFileTracing (PR) 行為,並移除已棄用的選項
  • [重大變更] 移除 Speed Insights 的自動檢測(現在必須使用專用的 @vercel/speed-insights 套件)(PR)
  • [重大變更] 移除動態網站地圖 (sitemap) 路由的 .xml 擴展名,並在開發和生產環境中統一網站地圖 URL (PR)
  • [改進] 元資料 (Metadata):更新了在 Vercel 上託管時 metadataBase 的環境變數回退 (PR)
  • [改進] 修復了 optimizePackageImports 中混合命名空間和命名導入時的樹搖 (tree-shaking) 問題 (PR)
  • [改進] 平行路由 (Parallel Routes):為未匹配的 catch-all 路由提供所有已知參數 (PR)
  • [改進] 配置 bundlePagesExternals 現已穩定並更名為 bundlePagesRouterDependencies
  • [改進] 配置 serverComponentsExternalPackages 現已穩定並更名為 serverExternalPackages
  • [改進] create-next-app:新專案預設忽略所有 .env 文件 (PR)
  • [文件] 改進身份驗證文件 (PR)
  • [文件] @next/env 套件 (PR)

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

貢獻者

Next.js 是超過 3,000 名獨立開發者、Google 和 Meta 等行業合作夥伴以及我們 Vercel 核心團隊共同努力的成果。此版本由以下人員共同完成:

特別感謝 @devjiwonchoi、@ijjk、@Ethan-Arrowood、@sokra、@kenji-webdev、@wbinnssmith、@huozhi、@domdomegg、@samcx、@Jaaneek、@evanwinter、@wyattjoh、@kdy1、@balazsorban44、@feedthejim、@ztanner、@ForsakenHarmony、@kwonoj、@delbaoliveira、@stipsan、@leerob、@shuding、@xiaohanyu、@timneutkens、@dvoytenko、@bobaaaaa、@bgw、@gaspar09、@souporserious、@unflxw、@kiner-tang、@Ehren12、@EffectDoplera、@IAmKushagraSharma、@Auxdible、@sean-rallycry、@Jeffrey-Zutt、@eps1lon、@jeanmax1me、@unstubbable、@NilsJacobsen、@PaulAsjes、@adiguno、@ryan-nauman、@zsh77、@KagamiChan、@steveluscher、@MehfoozurRehman、@vkryachko、@chentsulin、@samijaber、@begalinsaf、@FluxCapacitor2、@lukahartwig、@brianshano、@pavelglac、@styfle、@symant233、@HristovCodes、@karlhorky、@jonluca、@jonathan-ingram、@mknichel、@sopranopillow、@Gomah、@imddc、@notrab、@gabrielrolfsen、@remorses、@AbhiShake1、@agadzik、@ryota-murakami、@rishabhpoddar、@rezamauliadi、@IncognitoTGT、@webtinax、@BunsDev、@nisabmohd、@z0n、@bennettdams、@joeshub、@n1ckoates、@srkirkland、@RiskyMH、@coopbri、@okoyecharles、@diogocapela、@dnhn、@typeofweb、@davidsa03、@imranolas、@lubieowoce、@maxhaomh、@mirasayon、@blvdmitry、@hwangstar156、@lforst、@emmerich、@christian-bromann、@Lsnsh、@datner、@hiro0218、@flybayer、@ianmacartney、@ypessoa、@ryohidaka、@icyJoseph、@Arinji2、@lovell、@nsams、@Nayeem-XTREME、@JamBalaya56562、@Arindam200、@gaojude、@qqww08、@todor0v、@coltonehrman 和 @wiesson 的幫助!