跳至內容
返回部落格

2024 年 10 月 21 日,星期一

Next.js 15

發佈者

Next.js 15 正式版已發佈,可立即用於生產環境。此版本建基於 RC1 和 RC2 的更新,我們除了新增一些令人興奮的功能外,也著重於提升穩定性。立即試用 Next.js 15

終端機
# Use the new automated upgrade CLI
npx @next/codemod@canary upgrade latest
 
# ...or upgrade manually
npm install next@latest react@rc react-dom@rc

我們也很興奮地分享更多關於本週四,10 月 24 日 Next.js Conf 的最新消息。

以下是 Next.js 15 的新功能

使用 @next/codemod CLI 順利升級

我們在每個 Next.js 主要版本中都包含程式碼修改器(自動程式碼轉換),以協助自動升級重大變更。

為了讓升級更順暢,我們發布了增強的程式碼修改器 CLI

終端機
npx @next/codemod@canary upgrade latest

此工具可協助您將程式碼庫升級到最新的穩定版或預發布版本。CLI 將更新您的依賴項,顯示可用的程式碼修改器,並引導您應用它們。

canary 標籤使用最新版本的程式碼修改器,而 latest 指定 Next.js 版本。即使您要升級到最新的 Next.js 版本,我們也建議您使用 canary 版本的程式碼修改器,因為我們計劃根據您的回饋繼續改進此工具。

深入瞭解 Next.js 程式碼修改器 CLI

非同步請求 API(重大變更)

在傳統的伺服器端渲染中,伺服器會在渲染任何內容之前等待請求。然而,並非所有組件都依賴於請求的特定資料,因此不必等待請求來渲染它們。理想情況下,伺服器應在請求到達之前盡可能做好準備。為了實現這一點,並為未來的最佳化奠定基礎,我們需要知道何時等待請求。

因此,我們正在將依賴請求特定資料(例如 headerscookiesparamssearchParams)的 API 轉換為**非同步**。

import { cookies } from 'next/headers';
 
export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
 
  // ...
}

這是一個**重大變更**,會影響以下 API:

  • cookies
  • headers
  • draftMode
  • layout.jspage.jsroute.jsdefault.jsgenerateMetadatagenerateViewport 中的 params
  • page.js 中的 searchParams

為了簡化遷移,這些 API 可以暫時以同步方式存取,但在下一個主要版本之前,開發和生產環境中都會顯示警告。我們提供了一個程式碼修改器 (codemod)來自動化遷移過程。

終端機
npx @next/codemod@canary next-async-request-api .

如果程式碼修改器無法完全遷移您的程式碼,請閱讀升級指南。我們還提供了一個範例,說明如何將 Next.js 應用程式遷移到新的 API。

快取語義

Next.js App Router 推出時,預設採用了特定快取策略。這些策略旨在預設提供最佳效能,並允許在需要時選擇停用。

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

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

我們將在接下來的幾個月中持續改進 Next.js 中的快取功能,並將很快分享更多詳細資訊。

fetch 請求預設不再快取

Next.js 使用 網頁 fetch API 的快取選項來設定伺服器端提取請求與框架持久性 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 請求,方法如下:

  • 在單個 fetch 呼叫中將 cache 選項 設定為 force-cache
  • 將單一路由的 dynamic 路由設定選項 設定為 'force-static'
  • fetchCache 路由設定選項 設定為 'default-cache',以覆寫版面配置或頁面中的所有 fetch 請求,使其使用 force-cache,除非它們明確指定了自己的 cache 選項。

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 標記,允許自訂 路由器快取 的設定。

在 Next.js 15 中,這個標記仍然可以使用,但我們將預設行為更改為頁面區段的 staleTime0。這表示當您在應用程式中導覽時,用戶端將始終反映導覽過程中啟用的頁面組件的最新資料。然而,仍然有一些重要的行為保持不變:

  • 共用的版面配置資料不會從伺服器重新提取,以繼續支援 部分渲染
  • 前後導覽仍會從快取還原,以確保瀏覽器可以恢復捲動位置。
  • loading.js 將會被快取 5 分鐘(或 staleTimes.static 設定值)。

您可以透過設定以下配置來選擇先前的用戶端路由器快取行為

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

React 19

作為 Next.js 15 版本的一部分,我們決定與即將發佈的 React 19 保持一致。

在版本 15 中,應用程式路由器使用 React 19 RC,並且根據社群的回饋,我們也為頁面路由器引入了 React 18 的向下相容性。如果您正在使用頁面路由器,這允許您在準備就緒時升級到 React 19。

雖然 React 19 仍處於 RC 階段,但我們在實際應用程式中進行的廣泛測試以及與 React 團隊的密切合作,使我們對其穩定性充滿信心。核心的重大變更已經過充分測試,不會影響現有的應用程式路由器使用者。因此,我們決定現在將 Next.js 15 作為穩定版本發佈,以便您的專案為 React 19 正式版做好充分準備。

為了確保轉換過程盡可能順利,我們提供了程式碼修改器和自動化工具來協助簡化遷移過程。

閱讀Next.js 15 升級指南React 19 升級指南,並觀看React Conf Keynote以了解更多資訊。

在 React 18 上的頁面路由器

Next.js 15 保持了頁面路由器與 React 18 的向下相容性,允許使用者在繼續使用 React 18 的同時,也能受益於 Next.js 15 的改進。

自第一個候選版本 (RC1) 以來,我們已根據社群的回饋,將重點轉移到包含對 React 18 的支援。這種靈活性使您能夠在使用 React 18 的頁面路由器的同時採用 Next.js 15,讓您可以更好地控制升級路徑。

注意:雖然可以在同一個應用程式中同時執行 React 18 的頁面路由器和 React 19 的應用程式路由器,但我們不建議這種設定。這樣做可能會導致不可預測的行為和類型不一致,因為兩個版本之間的底層 API 和渲染邏輯可能無法完全一致。

React 編譯器(實驗性)

由 Meta 的 React 團隊創建的React 編譯器是一個全新的實驗性編譯器。該編譯器透過理解純 JavaScript 語義和React 規則,能夠深入理解您的程式碼,從而自動優化程式碼。編譯器減少了開發人員需要透過 useMemouseCallback 等 API 進行手動記憶體優化的工作量,使程式碼更簡潔、更容易維護,並且更不容易出錯。

在 Next.js 15 中,我們新增了對React 編譯器的支援。深入瞭解 React 編譯器以及可用的 Next.js 設定選項

注意:React 編譯器目前僅作為 Babel 外掛程式提供,這將導致開發和建置時間變慢。

Hydration 錯誤改進

Next.js 14.1 做了一些改進,改善了錯誤訊息和 hydration 錯誤。Next.js 15 在此基礎上繼續發展,新增了改進的 hydration 錯誤檢視。Hydration 錯誤現在會顯示錯誤的原始碼,並提供有關如何解決問題的建議。

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

Hydration error message in Next.js 14.1

Next.js 15 已將其改進為

Hydration error message improved in Next.js 15

Turbopack 開發模式

我們很高興地宣布,next dev --turbo 現在已穩定且準備就緒,可加快您的開發體驗。我們一直使用它來迭代 vercel.comnextjs.orgv0 以及我們所有其他的應用程式,並獲得了很棒的成果。

例如,在 vercel.com 這個大型 Next.js 應用程式中,我們觀察到:

  • 本機伺服器啟動速度提升高達 76.7%
  • 使用 Fast Refresh 更新程式碼的速度提升高達 96.3%
  • 在沒有快取的情況下,初始路由編譯速度提升高達 45.8%(Turbopack 目前還沒有磁碟快取功能)。

您可以在我們新的 部落格文章 中了解更多關於 Turbopack 開發模式的資訊。

靜態路由指示器

Next.js 現在在開發過程中會顯示靜態路由指示器,以協助您識別哪些路由是靜態或動態的。此視覺提示可讓您更輕鬆地了解頁面的渲染方式,從而最佳化效能。

您也可以使用 next build 輸出來查看所有路由的渲染策略。

此更新是我們持續努力強化 Next.js 可觀察性的一部分,讓開發人員更容易監控、除錯和最佳化他們的應用程式。我們也正在開發專用的開發人員工具,更多詳細資訊將很快推出。

進一步了解可停用的 靜態路由指示器

使用 unstable_after 在回應後執行程式碼(實驗性)

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

由於這些任務與回應沒有直接關係,使用者不應該需要等待它們完成。在回應使用者後延遲工作會帶來挑戰,因為無伺服器函式會在回應關閉後立即停止計算。

after() 是一個新的實驗性 API,它透過允許您在回應完成串流後安排要處理的工作來解決這個問題,從而使次要任務能夠在不阻塞主要回應的情況下運行。

要使用它,請將 experimental.after 添加到 next.config.js 中。

next.config.ts
const nextConfig = {
  experimental: {
    after: true,
  },
};
 
export default nextConfig;

然後,在伺服器元件、伺服器動作、路由處理程式或中介軟體中導入該函式。

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

進一步了解 unstable_after

instrumentation.js(穩定版)

具有 register() API 的 instrumentation 檔案允許使用者介入 Next.js 伺服器生命週期,以監控效能、追蹤錯誤來源,並與像是 OpenTelemetry 等可觀察性函式庫深度整合。

此功能現在已進入**穩定版**,可以移除 experimental.instrumentationHook 設定選項。

此外,我們還與 Sentry 合作設計了一個新的 onRequestError 鉤子,可用於

  • 擷取伺服器上所有拋出錯誤的重要上下文,包括
    • 路由器:頁面路由器或應用程式路由器
    • 伺服器上下文:伺服器元件、伺服器動作、路由處理程式或中介軟體
  • 將錯誤回報給您偏好的可觀察性供應商。
export async function onRequestError(err, request, context) {
  await fetch('https://...', {
    method: 'POST',
    body: JSON.stringify({ message: err.message, request, context }),
    headers: { 'Content-Type': 'application/json' },
  });
}
 
export async function register() {
  // init your favorite observability provider SDK
}

進一步了解 onRequestError 函式

<Form> 元件

全新的 <Form> 元件,基於 HTML 的 <form> 元素,並擴充了預取客戶端導航以及漸進式增強的功能。

它適用於會導航到新頁面的表單,例如會導向到結果頁面的搜尋表單。

app/page.jsx
import Form from 'next/form';
 
export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  );
}

<Form> 元件內建以下功能:

  • 預取:當表單在視窗內時,會預取佈局載入中的 UI,讓導航速度更快。
  • 客戶端導航:送出表單時,共用的佈局和客戶端狀態會被保留。
  • 漸進式增強:如果 JavaScript 尚未載入,表單仍然可以透過整頁導航的方式運作。

以前,要實現這些功能需要大量的手動樣板程式碼。例如:

範例
// Note: This is abbreviated for demonstration purposes.
// Not recommended for use in production code.
 
'use client'
 
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
 
export default function Form(props) {
  const action = props.action
  const router = useRouter()
 
  useEffect(() => {
    // if form target is a URL, prefetch it
    if (typeof action === 'string') {
      router.prefetch(action)
    }
  }, [action, router])
 
  function onSubmit(event) {
    event.preventDefault()
 
    // grab all of the form fields and trigger a `router.push` with the data URL encoded
    const formData = new FormData(event.currentTarget)
    const data = new URLSearchParams()
 
    for (const [name, value] of formData) {
      data.append(name, value as string)
    }
 
    router.push(`${action}?${data.toString()}`)
  }
 
  if (typeof action === 'string') {
    return <form onSubmit={onSubmit} {...props} />
  }
 
  return <form {...props} />
}

深入了解<Form> 元件

支援 next.config.ts

Next.js 現在支援 TypeScript 的 next.config.ts 檔案類型,並提供 NextConfig 類型以提供自動完成和類型安全選項。

next.config.ts
import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  /* config options here */
};
 
export default nextConfig;

深入了解 Next.js 中的TypeScript 支援

自行託管的改進

在自行託管應用程式時,您可能需要對 Cache-Control 指令進行更多控制。

一個常見的情況是控制傳送給 ISR 頁面的 stale-while-revalidate 期間。我們已經實作了兩項改進:

  1. 您現在可以在 next.config 中設定expireTime值。這以前是 experimental.swrDelta 選項。
  2. 將預設值更新為一年,確保大多數 CDN 可以完全按照預期應用 stale-while-revalidate 語義。

我們也不再使用我們的預設值覆蓋自訂的 Cache-Control 值,允許完全控制並確保與任何 CDN 設定的相容性。

最後,我們改進了自行託管時的圖片最佳化。以前,我們建議您安裝 sharp 以在您的 Next.js 伺服器上最佳化圖片。這個建議有時會被忽略。使用 Next.js 15,您不再需要手動安裝 sharp — Next.js 在使用 next start 或以獨立輸出模式執行時會自動使用 sharp

要了解更多資訊,請參閱我們新的關於自行託管 Next.js 的示範和教學影片

伺服器動作的安全性增強

伺服器動作 是可以從客戶端呼叫的伺服器端函式。它們的定義方式是在檔案頂部添加 'use server' 指令,並匯出一個非同步函式。

即使伺服器動作或工具函式未在程式碼的其他地方匯入,它仍然是一個公開可存取的 HTTP 端點。雖然這種行為在技術上是正確的,但它可能導致這些函式意外暴露。

為了提升安全性,我們引入了以下增強功能:

  • 無用程式碼移除:未使用的伺服器動作的 ID 不會暴露給客戶端 JavaScript 捆綁包,從而減少捆綁包大小並提升效能。
  • 安全的動作 ID:Next.js 現在會建立不可猜測、非確定性的 ID,以允許客戶端參考和呼叫伺服器動作。為了增強安全性,這些 ID 會在每次建構之間定期重新計算。
// app/actions.js
'use server';
 
// This action **is** used in our application, so Next.js
// will create a secure ID to allow the client to reference
// and call the Server Action.
export async function updateUserAction(formData) {}
 
// This action **is not** used in our application, so Next.js
// will automatically remove this code during `next build`
// and will not create a public endpoint.
export async function deleteUserAction(formData) {}

您仍然應該將伺服器動作視為公開的 HTTP 端點。進一步了解保護伺服器動作

外部套件的捆綁最佳化(穩定版)

捆綁外部套件可以提升應用程式的冷啟動效能。在應用程式路由器中,外部套件預設會被捆綁,您可以使用新的 serverExternalPackages 設定選項選擇排除特定套件。

頁面路由器中,外部套件預設不會被捆綁,但您可以使用現有的 transpilePackages 選項提供要捆綁的套件清單。使用此設定選項,您需要指定每個套件。

為了統一應用程式路由器和頁面路由器之間的設定,我們引入了新的選項 bundlePagesRouterDependencies,以符合應用程式路由器的預設自動捆綁行為。然後,您可以使用 serverExternalPackages 選項來選擇排除特定套件(如果需要)。

next.config.ts
const nextConfig = {
  // Automatically bundle external packages in the Pages Router:
  bundlePagesRouterDependencies: true,
  // Opt specific packages out of bundling for both App and Pages Router:
  serverExternalPackages: ['package-name'],
};
 
export default nextConfig;

進一步了解外部套件的最佳化

支援 ESLint 9

隨著 ESLint 8 於 2024 年 10 月 5 日終止服務,Next.js 15 也引入了對 ESLint 9 的支援。

為了確保順暢的過渡,Next.js 保持向下相容,這表示您可以繼續使用 ESLint 8 或 9。

如果您升級到 ESLint 9,且我們偵測到您尚未採用新的設定格式,Next.js 會自動套用 ESLINT_USE_FLAT_CONFIG=false 的相容模式設定,以簡化遷移過程。

此外,執行 next lint 時,將會移除已棄用的選項,例如 —ext—ignore-path。請注意,ESLint 最終將在 ESLint 10 中禁止這些較舊的設定,因此我們建議您盡快開始遷移。

有關這些變更的更多詳細資訊,請查看遷移指南

作為此更新的一部分,我們也將 eslint-plugin-react-hooks 升級到 v5.0.0,其中引入了新的 React Hooks 使用規則。您可以在eslint-plugin-react-hooks@5.0.0 的更新日誌中查看所有變更。

開發和建置的改進

伺服器元件熱模組更新 (HMR)

在開發過程中,伺服器元件會在儲存時重新執行。這表示,任何對您的 API 端點或第三方服務的 fetch 請求也會被呼叫。

為了提升本地開發效能並降低計費 API 呼叫的潛在成本,我們現在確保熱模組更新 (HMR) 可以重複使用先前渲染的 fetch 回應。

深入瞭解伺服器元件 HMR 快取

更快的應用路由器靜態生成

我們已最佳化靜態生成,以縮短建置時間,尤其是針對具有緩慢網路請求的頁面。

先前,我們的靜態最佳化流程會渲染頁面兩次 — 第一次是產生客戶端導航的數據,第二次是渲染初始頁面訪問的 HTML。現在,我們會重複使用第一次渲染,省去第二次的過程,減少工作負載和建置時間。

此外,靜態生成工作程序現在會跨頁面共享 fetch 快取。如果 fetch 呼叫沒有選擇停用快取,其結果會被同一個工作程序處理的其他頁面重複使用。這減少了對相同數據的請求次數。

進階靜態生成控制(實驗性)

我們已新增實驗性支援,可更精細地控制靜態生成流程,適用於需要更強控制能力的進階使用案例。

除非您有特定需求,否則我們建議您繼續使用目前的預設值,因為這些選項可能會導致資源使用量增加,並因並行性增加而導致潛在的記憶體不足錯誤。

next.config.ts
const nextConfig = {
  experimental: {
    // how many times Next.js will retry failed page generation attempts
    // before failing the build
    staticGenerationRetryCount: 1
    // how many pages will be processed per worker
    staticGenerationMaxConcurrency: 8
    // the minimum number of pages before spinning up a new export worker
    staticGenerationMinPagesPerWorker: 25
  },
}
 
export default nextConfig;

深入瞭解靜態生成選項

其他變更

  • [重大變更] next/image:移除 squoosh,改用 sharp 作為選用依賴項 (PR)
  • [重大變更] next/image:將預設 Content-Disposition 變更為 attachment (PR)
  • [重大變更] next/image:當 src 具有前導或尾端空格時會產生錯誤 (PR)
  • [重大變更] 中介軟體:套用 react-server 條件以限制不建議的 React API 導入 (PR)
  • [重大變更] next/font:移除對外部 @next/font 套件的支援 (PR)
  • [重大變更] next/font:移除 font-family 雜湊值 (PR)
  • [重大變更] 快取:force-dynamic 現在會將提取快取的預設值設為 no-store (PR)
  • [重大變更] 設定:預設啟用 swcMinify (PR)、missingSuspenseWithCSRBailout (PR) 和 outputFileTracing (PR) 的行為,並移除已棄用的選項。
  • [重大變更] 移除 Speed Insights 的自動檢測(現在必須使用專用的 @vercel/speed-insights 套件)(PR)
  • [重大變更] 移除動態 Sitemap 路由的 .xml 副檔名,並在開發和生產環境中對齊 Sitemap 網址 (PR)
  • [重大變更] 我們已棄用在 App Router 中匯出 export const runtime = "experimental-edge" 的方式。使用者現在應該改用 export const runtime = "edge"。我們已新增一個程式碼轉換工具來執行此操作(PR
  • [重大變更] 在渲染期間呼叫 revalidateTagrevalidatePath 現在會拋出錯誤(PR
  • [重大變更] instrumentation.jsmiddleware.js 檔案現在將使用供應商提供的 React 套件(PR
  • [重大變更] 最低所需的 Node.js 版本已更新至 18.18.0(PR
  • [重大變更] next/dynamic:已移除已棄用的 suspense 屬性,並且當元件在 App Router 中使用時,它將不再插入空的 Suspense 邊界(PR
  • [重大變更] 在 Edge Runtime 上解析模組時,將不會套用 worker 模組條件(PR
  • [重大變更] 不允許在伺服器元件中將 ssr: false 選項與 next/dynamic 一起使用(PR
  • [改進] 中繼資料:在 Vercel 上託管時,更新了 metadataBase 的環境變數後援值(PR
  • [改善] 修復了`optimizePackageImports`在混合使用命名空間和命名導入時的 Tree-shaking 問題 (PR)
  • [改善] 平行程式路由:為不匹配的全域路由提供所有已知參數 (PR)
  • [改善] 設定`bundlePagesExternals`現在已穩定,並更名為`bundlePagesRouterDependencies`
  • [改善] 設定`serverComponentsExternalPackages`現在已穩定,並更名為`serverExternalPackages`
  • [改善] create-next-app:新專案預設忽略所有`.env`檔案 (PR)
  • [改善] `outputFileTracingRoot`、`outputFileTracingIncludes`和`outputFileTracingExcludes`已從實驗性功能升級為穩定功能 (PR)
  • [改善] 避免將全域 CSS 檔案與樹狀結構更深層的 CSS 模組檔案合併 (PR)
  • [改善] 現在可以透過`NEXT_CACHE_HANDLER_PATH`環境變數指定快取處理器 (PR)
  • [改善] 頁面路由器現在同時支援 React 18 和 React 19 (PR)
  • [改善] 錯誤覆蓋層現在會顯示一個按鈕,以便在啟用檢查器的情況下複製 Node.js 檢查器網址 (PR)
  • [改善] App Router 上的客戶端預提取現在使用 priority 屬性 (PR)
  • [改善] Next.js 現在提供了一個 unstable_rethrow 函式,可以在 App Router 中重新拋出 Next.js 內部錯誤 (PR)
  • [改善] unstable_after 現在可以在靜態頁面中使用 (PR)
  • [改善] 如果在 SSR 期間使用了 next/dynamic 元件,則會預提取區塊 (PR)
  • [改善] App Router 現在支援 esmExternals 選項 (PR)
  • [改善] experimental.allowDevelopmentBuild 選項可用於允許在 next build 中使用 NODE_ENV=development 進行除錯 (PR)
  • [改善] 伺服器動作轉換現已在 Pages Router 中停用 (PR)
  • [改善] 建置工具現在會在退出時停止掛起的建置 (PR)
  • [改善] 從伺服器動作重新導向時,重新驗證現在將正確套用 (PR)
  • [改善] 現在 Edge 執行環境中的平行路由能正確處理動態參數 (PR)
  • [改善] 靜態頁面現在將在初始載入後遵守 staleTime 設定 (PR)
  • [改善] 更新 vercel/og,修復了記憶體洩漏問題 (PR)
  • [改善] 更新了修補程式碼的時機,允許使用像是 msw 之類的套件來模擬 API (PR)
  • [改善] 預渲染的頁面應使用靜態 staleTime 設定 (PR)

欲了解更多資訊,請參閱 升級指南

貢獻者

Next.js 是超過 3,000 位個別開發者、Google 和 Meta 等產業合作夥伴,以及我們在 Vercel 的核心團隊共同努力的成果。此版本由以下人員貢獻:

非常感謝 @AbhiShake1, @Aerilym, @AhmedBaset, @AnaTofuZ, @Arindam200, @Arinji2, @ArnaudFavier, @ArnoldVanN, @Auxdible, @B33fb0n3, @Bhavya031, @Bjornnyborg, @BunsDev, @CannonLock, @CrutchTheClutch, @DeepakBalaraman, @DerTimonius, @Develliot, @EffectDoplera, @Ehren12, @Ethan-Arrowood, @FluxCapacitor2, @ForsakenHarmony, @Francoscopic, @Gomah, @GyoHeon, @Hemanshu-Upadhyay, @HristovCodes, @HughHzyb, @IAmKushagraSharma, @IDNK2203, @IGassmann, @ImDR, @IncognitoTGT, @Jaaneek, @JamBalaya56562, @Jeffrey-Zutt, @JohnGemstone, @JoshuaKGoldberg, @Julian-Louis, @Juneezee, @KagamiChan, @Kahitar, @KeisukeNagakawa, @KentoMoriwaki, @Kikobeats, @KonkenBonken, @Kuboczoch, @Lada496, @LichuAcu, @LorisSigrist, @Lsnsh, @Luk-z, @Luluno01, @M-YasirGhaffar, @Maaz-Ahmed007, @Manoj-M-S, @ManuLpz4, @Marukome0743, @MaxLeiter, @MehfoozurRehman, @MildTomato, @MonstraG, @N2D4, @NavidNourani, @Nayeem-XTREME, @Netail, @NilsJacobsen, @Ocheretovich, @OlyaPolya, @PapatMayuri, @PaulAsjes, @PlagueFPS, @ProchaLu, @Pyr33x, @QiuranHu, @RiskyMH, @Sam-Phillemon9493, @Sayakie, @Shruthireddy04, @SouthLink, @Strift, @SukkaW, @Teddir, @Tim-Zj, @TrevorSayre, @Unsleeping, @Willem-Jaap, @a89529294, @abdull-haseeb, @abhi12299, @acdlite, @actopas, @adcichowski, @adiguno, @agadzik, @ah100101, @akazwz, @aktoriukas, @aldosch, @alessiomaffeis, @allanchau, @alpedia0, @amannn, @amikofalvy, @anatoliik-lyft, @anay-208, @andrii-bodnar, @anku255, @ankur-dwivedi, @aralroca, @archanaagivale30, @arlyon, @atik-persei, @avdeev, @baeharam, @balazsorban44, @bangseongbeom, @begalinsaf, @bennettdams, @bewinsnw, @bgw, @blvdmitry, @bobaaaaa, @boris-szl, @bosconian-dynamics, @brekk, @brianshano, @cfrank, @chandanpasunoori, @chentsulin, @chogyejin, @chrisjstott, @christian-bromann, @codeSTACKr, @coderfin, @coltonehrman, @controversial, @coopbri, @creativoma, @crebelskydico, @crutchcorn, @darthmaim, @datner, @davidsa03, @delbaoliveira, @devjiwonchoi, @devnyxie, @dhruv-kaushik, @dineshh-m, @diogocapela, @dnhn, @domdomegg, @domin-mnd, @dvoytenko, @ebCrypto, @ekremkenter, @emmerich, @flybayer, @floriangosse, @forsakenharmony, @francoscopic, @frys, @gabrielrolfsen, @gaojude, @gdborton, @greatvivek11, @gnoff, @guisehn, @GyoHeon, @hamirmahal, @hiro0218, @hirotomoyamada, @housseindjirdeh, @hungdoansy, @huozhi, @hwangstar156, @iampoul, @ianmacartney, @icyJoseph, @ijjk, @imddc, @imranolas, @iscekic, @jantimon, @jaredhan418, @jeanmax1me, @jericopulvera, @jjm2317, @jlbovenzo, @joelhooks, @joeshub, @jonathan-ingram, @jonluca, @jontewks, @joostmeijles, @jophy-ye, @jordienr, @jordyfontoura, @kahlstrm, @karlhorky, @karlkeefer, @kartheesan05, @kdy1, @kenji-webdev, @kevva, @khawajaJunaid, @kidonng, @kiner-tang, @kippmr, @kjac, @kjugi, @kshehadeh, @kutsan, @kwonoj, @kxlow, @leerob, @lforst, @li-jia-nan, @liby, @lonr, @lorensr, @lovell, @lubieowoce, @luciancah, @luismiramirez, @lukahartwig, @lumirlumir, @luojiyin1987, @mamuso, @manovotny, @marlier, @mauroaccornero, @maxhaomh, @mayank1513, @mcnaveen, @md-rejoyan-islam, @mehmetozguldev, @mert-duzgun, @mirasayon, @mischnic, @mknichel, @mobeigi, @molebox, @mratlamwala, @mud-ali, @n-ii-ma, @n1ckoates, @nattui, @nauvalazhar, @neila-a, @neoFinch, @niketchandivade, @nisabmohd, @none23, @notomo, @notrab, @nsams, @nurullah, @okoyecharles, @omahs, @paarthmadan, @pathliving, @pavelglac, @penicillin0, @phryneas, @pkiv, @pnutmath, @qqww08, @r34son, @raeyoung-kim, @remcohaszing, @remorses, @rezamauliadi, @rishabhpoddar, @ronanru, @royalfig, @rubyisrust, @ryan-nauman, @ryohidaka, @ryota-murakami, @s-ekai, @saltcod, @samcx, @samijaber, @sean-rallycry, @sebmarkbage, @shubh73, @shuding, @sirTangale, @sleevezip, @slimbde, @soedirgo, @sokra, @sommeeeer, @sopranopillow, @souporserious, @srkirkland, @steadily-worked, @steveluscher, @stipsan, @styfle, @stylessh, @syi0808, @symant233, @tariknh, @theoludwig, @timfish, @timfuhrmann, @timneutkens, @tknickman, @todor0v, @tokkiyaa, @torresgol10, @tranvanhieu01012002, @txxxxc, @typeofweb, @unflxw, @unstubbable, @versecafe, @vicb, @vkryachko, @wbinnssmith, @webtinax, @weicheng95, @wesbos, @whatisagi, @wiesson, @woutvanderploeg, @wyattjoh, @xiaohanyu, @xixixao, @xugetsu, @yosefbeder, @ypessoa, @ytori, @yunsii, @yurivangeffen, @z0n, @zce, @zhawtof, @zsh77 以及 @ztanner 的協助!