Back返回部落格

Next.js 14.1

Next.js 14 包含對自主託管、錯誤訊息、平行與攔截路由、Turbopack 等多項功能的改進。

Next.js 14.1 包含以下開發者體驗改進:

立即升級或使用以下指令開始:

Terminal
npx create-next-app@latest

自主託管改進

我們聽取了您對於如何透過 Node.js 伺服器、Docker 容器或靜態匯出來自主託管 Next.js 的改進建議。我們全面翻新了自主託管文件,內容包括:

在 Next.js 14.1 中,我們還穩定了針對增量靜態再生 (ISR) 的自訂快取處理器,以及為 App Router 提供更細粒度的資料快取:

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // 停用預設的記憶體快取
};

在自主託管時使用此配置對於 Kubernetes 等容器協調平台特別重要,因為每個 pod 都會有快取的副本。使用自訂快取處理器可確保所有託管 Next.js 應用的 pod 之間的一致性。

例如,您可以將快取值儲存在任何地方,如 Redis 或 Memcached。我們要特別感謝 @neshca 提供的 Redis 快取處理器適配器 與範例。

Turbopack 改進

我們持續專注於提升 Next.js 本地開發的可靠性和效能:

  • 可靠性:Turbopack 已通過完整的 Next.js 開發測試套件,並在 Vercel 應用中實際驗證
  • 效能:改善 Turbopack 初始編譯時間與 Fast Refresh 時間
  • 記憶體使用:優化 Turbopack 的記憶體使用量

我們計劃在未來的版本中穩定 next dev --turbo,目前仍為選用功能。

可靠性

使用 Turbopack 的 Next.js 現在已通過 5,600 項開發測試 (94%),比上次更新多了 600 項。您可以在 areweturboyet.com 追蹤進度。

我們持續在 Vercel 的所有 Next.js 應用(包括 vercel.comv0.dev)上實際使用 next dev --turbo。所有開發這些應用的工程師每天都在使用 Turbopack。

我們發現並修復了許多在大型 Next.js 應用中使用 Turbopack 的問題。針對這些修復,我們已在 Next.js 現有的開發測試套件中新增了測試。

效能

在大型 Next.js 應用 vercel.com 中,我們觀察到:

  • 本地伺服器啟動速度提升最高達 76.7%
  • 使用 Fast Refresh 的程式碼更新速度提升最高達 96.3%
  • 無快取時的初始路由編譯速度提升最高達 45.8%(Turbopack 目前尚未實現磁碟快取)

v0.dev 中,我們發現了優化 Turbopack 發現和打包 React 客戶端元件方式的機會,使初始編譯時間提升最高達 61.5%。此效能提升在 vercel.com 中也得到驗證。

未來改進

Turbopack 目前具有記憶體快取功能,可改善 Fast Refresh 的增量編譯時間。

然而,目前重啟 Next.js 開發伺服器時不會保留快取。Turbopack 效能的下一個重大改進是實現 磁碟快取,這將允許在重啟開發伺服器時保留快取。

開發體驗改進

改進的錯誤訊息與 Fast Refresh

我們清楚明確的錯誤訊息對本地開發體驗的重要性。我們已進行多項修正,以改善執行 next dev 時顯示的堆疊追蹤與錯誤訊息品質。

  • 先前顯示為打包工具錯誤(如 webpack-internal)的錯誤,現在能正確顯示錯誤的原始碼與受影響檔案。
  • 在客戶端元件中遇到錯誤並在編輯器中修正後,Fast Refresh 有時不會清除錯誤畫面,需要手動重新載入。我們已修復多個此類情況,例如嘗試從客戶端元件匯出 metadata

例如,這是先前的錯誤訊息:

Next.js 14 中 fetch 呼叫的錯誤範例

Next.js 14 中 fetch 呼叫的錯誤範例。

Next.js 14.1 已將此改進為:

渲染期間 fetch 呼叫的錯誤現在會顯示錯誤的原始碼與受影響檔案

渲染期間 fetch 呼叫的錯誤現在會顯示錯誤的原始碼與受影響檔案。

window.history.pushStatewindow.history.replaceState

App Router 現在允許使用原生 pushStatereplaceState 方法來更新瀏覽器的歷史堆疊,而無需重新載入頁面。

pushStatereplaceState 呼叫會與 Next.js App Router 整合,讓您可以與 usePathnameuseSearchParams 同步。

這在需要立即更新 URL 以保存狀態(如篩選條件、排序順序或其他需要在重新載入時保留的資訊)時特別有用。

'use client';
 
import { useSearchParams } from 'next/navigation';
 
export default function SortProducts() {
  const searchParams = useSearchParams();
 
  function updateSorting(sortOrder: string) {
    const params = new URLSearchParams(searchParams.toString());
    params.set('sort', sortOrder);
    window.history.pushState(null, '', `?${params.toString()}`);
  }
 
  return (
    <>
      <button onClick={() => updateSorting('asc')}>升冪排序</button>
      <button onClick={() => updateSorting('desc')}>降冪排序</button>
    </>
  );
}

了解更多關於在 Next.js 中使用 原生 History API 的資訊。

資料快取記錄功能

為了提升在執行 next dev 時對 Next.js 應用程式中快取資料的可觀測性,我們對 logging 配置選項 進行了多項改進。

現在您可以顯示快取是 HIT(命中)或 SKIP(跳過),以及完整的請求 URL:

Terminal
GET / 200 in 48ms
 Compiled /fetch-cache in 117ms
 GET /fetch-cache 200 in 165ms
 GET https://api.vercel.app/products/1 200 in 14ms (cache: HIT)
 Compiled /fetch-no-store in 150ms
 GET /fetch-no-store 200 in 548ms
 GET https://api.vercel.app/products/1 200 in 345ms (cache: SKIP)
  Cache missed reason: (cache: no-store)

可透過 next.config.js 啟用此功能:

next.config.js
module.exports = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
};

next/image<picture> 和藝術指導 (Art Direction) 的支援

Next.js 的 Image 元件現在透過 getImageProps()(穩定版)支援更多進階使用情境,這些情境無需直接使用 <Image>。包括:

import { getImageProps } from 'next/image';
 
export default function Page() {
  const common = { alt: 'Hero', width: 800, height: 400 };
  const {
    props: { srcSet: dark },
  } = getImageProps({ ...common, src: '/dark.png' });
  const {
    props: { srcSet: light, ...rest },
  } = getImageProps({ ...common, src: '/light.png' });
 
  return (
    <picture>
      <source media="(prefers-color-scheme: dark)" srcSet={dark} />
      <source media="(prefers-color-scheme: light)" srcSet={light} />
      <img {...rest} />
    </picture>
  );
}

了解更多關於 getImageProps() 的資訊。

平行路由 (Parallel) 與攔截路由 (Intercepted Routes)

在 Next.js 14.1 中,我們對平行路由與攔截路由進行了 20 項改進

在過去的兩個版本中,我們專注於提升 Next.js 的效能與穩定性。現在根據您的回饋,我們已能對 平行路由攔截路由 進行多項改進,特別是新增了對 catch-all 路由和伺服器動作 (Server Actions) 的支援。

  • 平行路由 讓您能在同一佈局中同時或有條件地渲染一個或多個頁面。對於應用程式中高度動態的部分,例如社交網站中的儀表板和動態消息,平行路由可用於實作複雜的路由模式。
  • 攔截路由 讓您能在當前佈局中載入應用程式其他部分的路由。例如,當點擊動態消息中的照片時,您可以在模態視窗中顯示該照片,覆蓋在動態消息上。在這種情況下,Next.js 會攔截 /photo/123 路由,遮罩 URL 並將其覆蓋在 /feed 上。

了解更多關於 平行路由攔截路由 的資訊,或 查看範例

其他改進

14.0 以來,我們已修復了許多社群高度關注的錯誤。

我們最近還發布了影片 解釋快取機制 和一些 使用 App Router 時的常見錯誤,您可能會覺得有幫助。

  • [文件] 新增關於 重新導向 (Redirecting) 的文件
  • [文件] 新增關於 測試 (Testing) 的文件
  • [文件] 新增包含 生產環境檢查清單 (Production Checklist) 的文件
  • [功能]next/third-parties 中新增 <GoogleAnalytics /> 元件 (文件)
  • [改進] create-next-app 現在更小且安裝更快 (PR)
  • [改進] 巢狀路由拋出的錯誤仍可被 global-error 捕獲 (PR)
  • [改進] redirect 現在在伺服器動作中使用時會尊重 basePath (PR)
  • [改進] 修正 next/scriptbeforeInteractive 與 App Router 的使用問題 (PR)
  • [改進] 自動轉譯 @aws-sdklodash 以加速路由啟動 (PR)
  • [改進] 修正 next devnext/font 導致的未樣式內容閃爍問題 (PR)
  • [改進]notFound 錯誤傳遞過區段的錯誤邊界 (PR)
  • [改進] 修正 Pages Router i18n 從本地化網域提供公開檔案的問題 (PR)
  • [改進] 當傳入無效的 revalidate 值時拋出錯誤 (PR)
  • [改進] 修正 Windows 上建立建置後在 Linux 機器上的路徑問題 (PR)
  • [改進] 修正使用多區域應用程式與 basePath 時的 Fast Refresh / HMR 問題 (PR)
  • [改進] 改善終止信號的優雅關閉 (PR)
  • [改進] 修正從不同路由攔截時的模態路由衝突問題 (PR)
  • [改進] 修正使用 basePath 配置時的攔截路由問題 (PR)
  • [改進] 當缺少平行插槽導致 404 時顯示警告 (PR)
  • [改進] 改善與 catch-all 路由搭配使用的攔截路由 (PR)
  • [改進] 改善與 revalidatePath 搭配使用的攔截路由 (PR)
  • [改進] 修正平行路由中 @children 插槽的使用問題 (PR)
  • [改進] 修正使用參數與平行路由時的 TypeError 問題 (PR)
  • [改進] 修正預設平行路由的 catch-all 路由標準化問題 (PR)
  • [改進] 修正 next build 摘要中平行路由的顯示問題 (PR)
  • [改進] 修正使用攔截路由時的路由參數問題 (PR)
  • [改進] 改善深度巢狀的平行/攔截路由 (PR)
  • [改進] 修正攔截路由與路由群組配對時的 404 問題 (PR)
  • [改進] 修正平行路由與伺服器動作 / 重新驗證路由快取的問題 (PR)
  • [改進] 修正 rewrites 與攔截路由的使用問題 (PR)
  • [改進] 伺服器動作現在可從第三方函式庫運作 (PR)
  • [改進] Next.js 現在可在 ESM 套件中使用 (PR)
  • [改進] 針對 Material UI 等函式庫的 Barrel 檔案最佳化 (PR)
  • [改進] 現在當錯誤使用 useSearchParams 而沒有 Suspense 時,建置會失敗 (PR)

貢獻者

Next.js 是超過 3,000 名獨立開發者、Google 和 Meta 等產業夥伴,以及 Vercel 核心團隊共同合作的成果。加入社群參與 GitHub DiscussionsRedditDiscord

本次發布由以下人員共同完成:

以及以下貢獻者: @OlehDutchenko, @eps1lon, @ebidel, @janicklas-ralph, @JohnPhamous, @chentsulin, @akawalsky, @BlankParticle, @dvoytenko, @smaeda-ks, @kenji-webdev, @rv-david, @icyJoseph, @dijonmusters, @A7med3bdulBaset, @jenewland1999, @mknichel, @kdy1, @housseindjirdeh, @max-programming, @redbmk, @SSakibHossain10, @jamesmillerburgess, @minaelee, @officialrajdeepsingh, @LorisSigrist, @yesl-kim, @StevenKamwaza, @manovotny, @mcexit, @remcohaszing, @ryo-manba, @TranquilMarmot, @vinaykulk621, @haritssr, @divquan, @IgorVaryvoda, @LukeSchlangen, @RiskyMH, @ash2048, @ManuWeb3, @msgadi, @dhayab, @ShahriarKh, @jvandenaardweg, @DestroyerXyz, @SwitchBladeAK, @ianmacartney, @justinh00k, @tiborsaas, @ArianHamdi, @li-jia-nan, @aramikuto, @jquinc30, @samcx, @Haosik, @AkifumiSato, @arnabsen, @nfroidure, @clbn, @siddtheone, @zbauman3, @anthonyshew, @alexfradiani, @CalebBarnes, @adk96r, @pacexy, @hichemfantar, @michaldudak, @redonkulus, @k-taro56, @mhughdo, @tknickman, @shumakmanohar, @vordgi, @hamirmahal, @gaspar09, @JCharante, @sjoerdvanBommel, @mass2527, @N-Ziermann, @tordans, @davidthorand, @rmathew8-gh, @chriskrogh, @shogunsea, @auipga, @SukkaW, @agustints, @OXXD, @clarencepenz, @better-salmon, @808vita, @coltonehrman, @tksst, @hugo-syn, @JakobJingleheimer, @Willem-Jaap, @brandonnorsworthy, @jaehunn, @jridgewell, @gtjamesa, @mugi-uno, @kentobento, @vivianyentran, @empflow, @samennis1, @mkcy3, @suhaotian, @imevanc, @d3lm, @amannn, @hallatore, @Dylan700, @mpsq, @mdio, @christianvuerings, @karlhorky, @simonhaenisch, @olci34, @zce, @LavaToaster, @rishabhpoddar, @jirihofman, @codercor, @devjiwonchoi, @JackieLi565, @thoushif, @pkellner, @jpfifer, @quisido, @tomfa, @raphaelbadia, @j9141997, @hongaar, @MadCcc, @luismulinari, @dumb-programmer, @nonoakij, @franky47, @robbertstevens, @bryndyment, @marcosmartini, @functino, @Anisi, @AdonisAgelis, @seangray-dev, @prkagrawal, @heloineto, @kn327, @ihommani, @MrNiceRicee, @falsepopsky, @thomasballinger, @tmilewski, @Vadman97, @dnhn, @RodrigoTomeES, @sadikkuzu, @gffuma, @Schniz, @joulev, @Athrun-Judah, @rasvanjaya21, @rashidul0405, @nguyenbry, @Mwimwii, @molebox, @mrr11k, @philwolstenholme, @IgorKowalczyk, @Zoe-Bot, @HanCiHu, @JackHowa, @goncy, @hirotomoyamada, @pveyes, @yeskunall, @ChendayUP, @hmaesta, @ajz003, @its-kunal, @joelhooks, @blurrah, @tariknh, @Vinlock, @Nayeem-XTREME, @aziyatali, @aspehler, 和 @moka-ayumu.