跳到內容
返回部落格

2024 年 10 月 15 日,星期二

Next.js 15 RC 2

作者:

繼五月份發布第一個 Next.js 15 候選版本 之後, 我們根據您的回饋,準備了第二個候選版本。以下是我們一直在努力的方向

立即試用 Next.js 15 候選版本 (RC2)

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

注意: 此候選版本包含 先前 RC 的所有變更。

透過 codemod CLI 順暢升級

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

為了使升級更加順暢,我們發布了增強的 codemod CLI

npx @next/codemod@canary upgrade rc

此工具可協助您將程式碼庫升級到最新的穩定或預發布版本。CLI 將更新您的依賴項、顯示可用的 codemod,並引導您套用它們。命令列上指定的發布標籤 (@rc@canary 等) 決定要升級到的版本。

深入了解 Next.js codemod

Turbopack for Development

用於本地開發的 Turbopack 將在 Next.js 15 的正式版本中成為穩定版,同時保持可選擇性。您今天可以透過執行以下命令來試用它

next dev --turbo

感謝數千名開發人員參與 Turbopack beta 和候選版本階段的測試、回報問題和驗證修復,自第一個 Next.js 15 候選版本以來,我們已解決了 54 個 GitHub 問題。除了社群的努力外,我們在 vercel.com v0.dev nextjs.org 上的內部測試,也協助識別出許多額外的改進。

在過去的三個月中,我們專注於最佳化冷編譯效能。與之前的版本相比,我們看到了

  • 25–35% 的減少 記憶體使用量。
  • 30–50% 更快的 具有數千個模組的大型頁面編譯速度。

我們將在未來的版本中繼續最佳化這些領域。

展望未來,Turbopack 團隊在持久快取、減少記憶體使用量和用於 next build 的 Turbopack 方面取得了重大進展 96% 的測試通過

注意: 請參閱 Turbopack 的所有 支援和不支援的功能

Async Request APIs (重大變更)

在傳統的伺服器端渲染中,伺服器會等待請求,然後才渲染任何內容。但是,並非所有元件都依賴於請求特定的資料,因此無需等待請求來渲染它們。理想情況下,伺服器會在請求到達之前盡可能地做好準備。為了啟用此功能,並為未來的最佳化奠定基礎,我們需要知道何時等待請求。

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

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

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

  • cookies
  • headers
  • draftMode
  • params layout.js page.js route.js default.js generateMetadata generateViewport
  • searchParams page.js

為了更輕鬆地遷移,這些 API 可以暫時同步存取,但在開發和生產環境中會顯示警告,直到下一個主要版本。提供了一個 codemod 來自動化遷移

npx @next/codemod@canary next-async-request-api .

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

Enhanced Security for Server Actions

Server Actions 是可從用戶端呼叫的伺服器端函式。它們的定義方式是在檔案頂部新增 '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 端點。深入了解 保護伺服器動作

Static Route Indicator

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

您也可以使用 next build 輸出,以檢視所有路由的渲染策略。

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

深入了解 靜態路由指示器,該指示器可以停用。

<Form> Component

新的 <Form> 元件使用 預先載入 用戶端導航 和漸進式增強功能擴展了 HTML <form> 元素。

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

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 類型,用於自動完成和型別安全選項

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

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

instrumentation.js (穩定版)

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

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

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

  • 擷取伺服器上拋出的所有錯誤的重要上下文,包括
    • 路由器:Pages Router 或 App Router
    • 伺服器上下文:伺服器元件、伺服器動作、路由處理常式或中介軟體
  • 將錯誤報告給您最喜歡的可觀察性供應商。
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 函式

Development and Build Improvements

Server Components HMR

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

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

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

Faster Static Generation for the App Router

我們最佳化了靜態產生,以改善建置時間,尤其對於具有慢速網路請求的頁面。

以前,我們的靜態最佳化流程會渲染頁面兩次一次產生用戶端導航的資料,第二次渲染初始頁面訪問的 HTML。現在,我們重複使用第一次渲染,省略第二次傳遞,減少工作量和建置時間。

此外,靜態產生工作執行緒現在跨頁面共用 fetch 快取。如果 fetch 呼叫未選擇退出快取,則其結果將由同一工作執行緒處理的其他頁面重複使用。這減少了對相同資料的請求數量。

Advanced Static Generation Control (實驗性)

我們新增了實驗性支援,以更精細地控制靜態產生流程,適用於希望從更精細控制中獲益的進階用例。

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

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;

深入了解 靜態產生選項

Improvements for self-hosting

在自行託管應用程式時,您可能需要更精細地控制 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 的新 示範和教學影片

ESLint 9 Support

在 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 的變更日誌 中查看所有變更。

其他變更

  • 先前在 RC 1 部落格文章 中描述的所有變更
  • [重大變更] 我們已棄用在 App Router 中匯出 export const runtime = "experimental-edge"。使用者現在應切換到 export const runtime = "edge"。我們新增了一個 codemod 來執行此操作 (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)
  • [重大變更] 禁止在伺服器組件中搭配 next/dynamic 使用 ssr: false 選項 (PR)
  • [改進] outputFileTracingRootoutputFileTracingIncludesoutputFileTracingExcludes 已從實驗性升級,現在已穩定 (PR)
  • [改進] 避免將全域 CSS 檔案與樹狀結構中更深層的 CSS 模組檔案合併 (PR)
  • [改進] 可以透過 NEXT_CACHE_HANDLER_PATH 環境變數指定快取處理器 (PR)
  • [改進] Pages Router 現在同時支援 React 18 和 React 19 (PR)
  • [改進] 錯誤覆蓋層現在會顯示一個按鈕,以便在啟用 inspector 時複製 Node.js Inspector URL (PR)
  • [改進] App Router 上的用戶端預先載入現在使用 priority 屬性 (PR)
  • [改進] Next.js 現在提供 unstable_rethrow 函數,以便在 App Router 中重新拋出 Next.js 內部錯誤 (PR)
  • [改進] unstable_after 現在可用於靜態頁面 (PR)
  • [改進] 如果在 SSR 期間使用 next/dynamic 組件,則會預先載入 chunk (PR)
  • [改進] App Router 現在支援 esmExternals 選項 (PR)
  • [改進] experimental.allowDevelopmentBuild 選項可用於允許 NODE_ENV=developmentnext build 搭配使用,以進行偵錯 (PR)
  • [改進] 伺服器行為轉換現在已在 Pages Router 中停用 (PR)
  • [改進] 建置 workers 現在會在結束時停止建置掛起 (PR)
  • [改進] 從伺服器行為重新導向時,重新驗證現在將正確套用 (PR)
  • [改進] 動態參數現在在 Edge Runtime 上針對平行路由正確處理 (PR)
  • [改進] 靜態頁面現在將在初始載入後遵循 staleTime (PR)
  • [改進] vercel/og 已更新,包含記憶體洩漏修復 (PR)
  • [改進] 修補程式計時已更新,允許使用類似 msw 的套件進行 API 模擬 (PR)

貢獻者

Next.js 是超過 3,000 位個別開發者以及 Vercel 核心團隊共同努力的成果。本次發布由以下人員為您帶來:

非常感謝 @huozhi、@shuding、@wyattjoh、@PaulAsjes、@mcnaveen、@timneutkens、@stipsan、@aktoriukas、@sirTangale、@greatvivek11、@sokra、@anatoliik-lyft、@wbinnssmith、@coltonehrman、@hungdoansy、@kxlow、@ztanner、@manovotny、@leerob、@ryota-murakami、@ijjk、@pnutmath、@feugy、@Jeffrey-Zutt、@wiesson、@eps1lon、@devjiwonchoi、@Ethan-Arrowood、@kenji-webdev、@domdomegg、@samcx、@Jaaneek、@evanwinter、@kdy1、@balazsorban44、@feedthejim、@ForsakenHarmony、@kwonoj、@delbaoliveira、@xiaohanyu、@dvoytenko、@bobaaaaa、@bgw、@gaspar09、@souporserious、@unflxw、@kiner-tang、@Ehren12、@EffectDoplera、@IAmKushagraSharma、@Auxdible、@sean-rallycry、@jeanmax1me、@unstubbable、@NilsJacobsen、@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、@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、@tokkiyaa、@arlyon、@lorensr、@Juneezee、@Sayakie、@IGassmann、@bosconian-dynamics、@phryneas、@akazwz、@atik-persei、@shubh73、@alpedia0、@chogyejin、@notomo、@ArnoldVanN、@dhruv-kaushik、@kevva、@Kahitar、@anay-208、@boris-szl、@devnyxie、@LorisSigrist、@M-YasirGhaffar、@Lada496、@kippmr、@torresgol10、@pkiv、@Netail、@jontewks、@ArnaudFavier、@chrisjstott、@mratlamwala、@mayank1513、@karlkeefer、@kshehadeh、@Marukome0743、@a89529294、@anku255、@KeisukeNagakawa、@andrii-bodnar、@aldosch、@versecafe、@steadily-worked、@cfrank、@QiuranHu、@farsabbutt、@joostmeijles、@saltcod、@archanaagivale30、@crutchcorn、@crebelskydico、@Maaz-Ahmed007、@jophy-ye、@remcohaszing、@JoshuaKGoldberg、@creativoma、@GyoHeon、@SukkaW、@MaxLeiter、@neila-a、@stylessh、@Teddir、@ManuLpz4、@Julian-Louis、@syi0808、@mert-duzgun、@amannn、@MonstraG、@hamirmahal、@tariknh、@Kikobeats、@LichuAcu、@Kuboczoch、@himself65、@Sam-Phillemon9493、@Shruthireddy04、@Hemanshu-Upadhyay、@timfuhrmann、@controversial、@pathliving、@mischnic、@mauroaccornero、@NavidNourani、@allanchau、@ekremkenter、@yurivangeffen、@gnoff、@darthmaim、@gdborton、@Willem-Jaap、@KentoMoriwaki、@TrevorSayre、@marlier、@Luluno01、@xixixao、@domin-mnd、@niketchandivade、@N2D4、@kjugi、@luciancah、@mud-ali、@codeSTACKr、@luojiyin1987、@mehmetozguldev、@ronanru、@tknickman、@joelhooks、@khawajaJunaid、@rubyisrust、@abdull-haseeb、@bewinsnw、@housseindjirdeh、@li-jia-nan、@aralroca、@s-ekai、@ah100101、@jantimon、@jordienr、@iscekic、@Strift、@slimbde、@nauvalazhar、@HughHzyb、@guisehn、@wesbos、@OlyaPolya、@paarthmadan、@AhmedBaset、@dineshh-m、@avdeev、@Bhavya031、@MildTomato、@Bjornnyborg、@amikofalvy、@yosefbeder、@kjac、@woutvanderploeg、@Ocheretovich、@ProchaLu、@luismiramirez、@omahs、@theoludwig、@abhi12299、@sommeeeer、@lumirlumir、@royalfig、@iampoul、@molebox、@txxxxc、@zce、@mamuso、@kahlstrm、@vercel-release-bot、@zhawtof、@PapatMayuri、@PlagueFPS、@IDNK2203、@jericopulvera、@liby、@CannonLock、@timfish、@whatisagi、@none23、@haouvw、@Pyr33x、@SouthLink、@frydj、@CrutchTheClutch、@sleevezip、@r34son、@yunsii、@md-rejoyan-islam、@kartheesan05、@nattui、@KonkenBonken、@weicheng95、@brekk、@Francoscopic、@B33fb0n3、@ImDR、@nurullah、@hdodov、@ebCrypto、@soedirgo、@floriangosse、@Tim-Zj、@raeyoung-kim、@erwannbst、@DerTimonius、@hirotomoyamada、@Develliot、@chandanpasunoori、@vicb、@ankur-dwivedi、@kidonng、@baeharam、@AnaTofuZ、@coderfin、@xugetsu、@alessiomaffeis、@kutsan、@jordyfontoura、@sebmarkbage、@tranvanhieu01012002、@jlbovenzo、@Luk-z、@jaredhan418、@bangseongbeom、@penicillin0、@neoFinch、@DeepakBalaraman、@Manoj-M-S、@Unsleeping、@lonr、@Aerilym、@ytori、@acdlite、@actopas、@n-ii-ma、@adcichowski、@mobeigi、@JohnGemstone 和 @jjm2317 的協助!