next-cache-components-adoption

next-cache-components-adoption

熱門

在 Next.js App 中啟用 Cache Components,並處理因而浮現的阻塞路由(blocking routes)。當使用者想要啟用、採用或遷移至 Cache Components、開啟 `cacheComponents` 標誌、處理大量 blocking-prerender / instant 驗證錯誤、執行 `cache-components-instant-false` codemod,或決定要在路由加上 `export const instant = false` 來排除驗證,還是直接就地修復時使用。

14萬星標
3.1萬分支
更新於 2026/7/24
SKILL.md
唯讀
名稱
next-cache-components-adoption
描述

在 Next.js App 中啟用 Cache Components,並處理因而浮現的阻塞路由(blocking routes)。當使用者想要啟用、採用或遷移至 Cache Components、開啟 `cacheComponents` 標誌、處理大量 blocking-prerender / instant 驗證錯誤、執行 `cache-components-instant-false` codemod,或決定要在路由加上 `export const instant = false` 來排除驗證,還是直接就地修復時使用。

next-cache-components-adoption

在 App 中啟用 Cache Components,並引導其一步步完成成功的建置(build)。本 Skill 用於安排工作流程;各項錯誤的具體解決方案,則位在 dev overlay 的修復卡片以及建置的終端機輸出中。遷移至 Cache Components 指南是本 Skill 所套用概念與各 API 解法的官方權威參考資料 —— 每當 Skill 步驟引用某種模式(例如 "use cache"cacheLife<Suspense> 的放置位置等)且你需要完整的詳細說明時,請參閱該指南。

requires

  • App Router 專案。 Cache Components 是 App Router 的功能;cacheComponents: truepages/ 路由沒有任何效果。如果專案只有 pages/src/pages/ 目錄,但沒有 app/src/app/ 目錄,請立刻停止並告知使用者 —— Pages → App 遷移本身是一個獨立的專案,不屬於本 Skill 的範疇。混合型 App(同時包含 pages/app/)則完全沒問題:該標誌只會影響 app/ 路由;pages/ 路由不受影響,也不需要設定排除(opt-out)。

  • 可執行的 App。 整個驗證循環都需要透過 next dev 與瀏覽器來進行,因此 App 必須能夠成功啟動。如果在匯入(import)時會讀取資料庫或必要的環境變數(例如在缺少 DATABASE_URL 時會拋出錯誤的 env.ts),請在進行步驟 1 前,先確認它在真實環境或你架設的本地資料中能正常啟動。無法執行的 App 是無法驗證採納進度的。

  • Next.js 16.3 或更新版本。 此版本開始才支援本 Skill 所依賴的相關功能:頂層 cacheComponentsexport const instant、dev overlay 的即時導覽驗證警告,以及 cache-components-instant-false codemod。如果 next --version 顯示低於 16.3,請先進行升級:

    • 執行 npx @next/codemod@latest upgrade latest 來套用跨版本的 codemod。
    • 閱讀相關的版本升級指南(例如 Version 16),了解 codemod 未涵蓋的部分。
  • 無不相容的設定鍵(config keys)。 cacheComponents: true 會對任何仍匯出 dynamicrevalidatefetchCache 的檔案報錯。請進行轉換,不要直接刪除。 每個匯出都代表該路由需要保留的行為;請透過遷移指南的各 key 章節,將每一個匯出轉譯為相對應的 Cache Components 模式。唯一的例外是 dynamic = 'force-dynamic':在 Cache Components 機制下,每個路由預設都已經是動態的,因此遷移指南會直接將其刪除而不是轉譯 —— 不需要對一整批相同的 force-dynamic 刪除操作過度思考。revalidatefetchCache 仍然需要實際的轉換。若某個值暫時無法乾淨地轉譯,請留下 // TODO: Cache Components adoption — restore revalidate = 3600 註解,以便後續循環能捕捉到。cache-components-instant-false codemod 不會動到這些設定。

  • experimental.dynamicIO 會導致致命錯誤(fatal)。 它已被重命名為頂層的 cacheComponents,舊的 key 會在任何建置執行前就直接中斷 —— 請先將其移除(或替換為 cacheComponents: true)。experimental.useCache 仍可作為已棄用(deprecated)的別名被接受;但在設定 cacheComponents: true 後便顯得多餘,建議一併移除以利清晰。

notes

  • 開啟標誌前無過關的基準。 若 App 已經在使用 "use cache",在開啟標誌前的建置會報錯 please enable the feature flag cacheComponents。開啟該標誌是你第一件要做的事(在漸進式流程中,位於 codemod 之前;在直接法流程中,位於修復路由之前)—— 而不是在獲得成功的建置_之後_才做的事。請在初始摘要中特別說明這一點,以免被誤解為退化(regression)。

  • 離線文件。 指南連結在 node_modules/next/dist/docs/ 下附有離線副本(自 Next.js 16.2 起內建),其目錄結構帶有數字編號以利排序(例如 node_modules/next/dist/docs/01-app/02-guides/migrating-to-cache-components.md)。如果你無法預測編號前綴,可以用 find node_modules/next/dist/docs -name '<slug>.md' 來解析。注意 /docs/messages/* 錯誤頁面並未打包在內。

  • 未內建文件的舊版本。 在開始前可向使用者建議執行 npx @next/codemod@latest agents-md:它會下載版本對應的副本至 .next-docs/,並在 AGENTS.md / CLAUDE.md 中寫入索引。因為這會修改專案儲存庫中的檔案,請先詢問使用者,獲得同意後再執行。

the shape of the work

工作流程只有一個主循環:由上而下走訪路由樹,一次處理一個功能,對照 next dev + 瀏覽器來採納每個路由。建置只是每個功能的最終檢查關卡,而不是主要的操作介面。

步驟 1 的選擇在於:要先將所有路由都排除(opt-out)驗證,還是一邊處理一邊修復路由。無論哪種方式,核心循環都是相同的:

  • 帶有安靜預先步驟(漸進式 Incremental)。 執行 codemod,將所有頁面與 layout 排除驗證。一旦你修復了 codemod 無法處理的部分(同步 IO 呼叫、殘留的 revalidate/dynamic/fetchCache 匯出),建置就會通過;你可以將其作為獨立的 PR 發送,接著開始主循環 —— 一次移除一個 opt-out 並採納該路由。這能把工作拆解成小型且易於審查的 PR。
  • 不帶預先步驟(直接法 Direct)。 啟用 cacheComponents,並直接從建置率先標示出的問題開始進入循環。循環完全相同,但所有修復都會留在同一分支上,直到採納完成。

在這兩種方式中,單一路由的成功標準都是相同的:dev loop 回報無錯誤,且 next build 通過。在完成每個功能後與使用者確認,並建議進行 commit,但未經使用者確認前切勿自行 commit。大部分時間應花在循環中,而不是預先步驟。

background

cacheComponents: true 要求每個路由都必須可預渲染(prerenderable)。在 <Suspense> 外部讀取請求階段資料(request-time data)的路由會被判定為「阻塞」(blocking)並導致建置失敗。export const instant = false 可將路由標記為允許阻塞,從而在 dev 和 build 中清除該錯誤;在 layout 上,它會在建置期間涵蓋整個子樹,但用戶端的導覽仍然會各自驗證每個子片段(descendant segment)。包裹在 "use cache" 函式中的讀取會被視為快取邊界(cache boundary),而非阻塞讀取。

通常會遇到三類阻塞原因,排查順序通常如下:

  1. 請求階段讀取(Request-time reads)cookies()headers()await paramsawait searchParams)。這四者若在 page 或 layout 頂層被 await,都會造成阻塞。paramssearchParams 經常被忽略,因為不像 cookies 和 headers 那樣直覺地被歸類為「請求資料」。修復方法是將讀取下移至包裹在 <Suspense> 中的子元件 —— 對於 params/searchParams,應將 promise 傳遞給子元件並在子元件中 await,不要在頁面頂層 await
  2. 模組/渲染階段的同步 IO(Sync-IO at module/render time)new Date()Date.now()Math.random()crypto.randomUUID())。即使設定了 instant = false,這些呼叫仍會導致建置失敗 —— opt-out 無法壓制它們。如果它們位於共享的 layout 中,就會阻塞其下的每一個路由。Codemod 無法自動修復它們;你必須在建置通過前手動轉換每一個(參見漸進式預先步驟)。在執行任何操作前,請先用 grep 搜尋整個專案中的這些呼叫。
  3. 讀取請求資料的 "use cache" 檔案。 包含頂層 "use cache" 指令的檔案不能匯出 instant;若兩者混用會引發錯誤:Only async functions are allowed to be exported in a "use cache" file.,這意味著該指令對該路由而言是錯誤的。在執行 codemod 前請先將其移除。

working surfaces

finding blocking routes

工作時,請優先使用 next dev 而非 next build

  • next dev —— 主要的工作介面。造訪某個路由;其阻塞錯誤會顯示在 dev overlay 中,並附帶完整的 stack trace,以及連結至各錯誤文件頁面的修復卡片。請一次處理一個路由 —— 錯誤不會全部累積在一處。路由本身仍會傳回 HTTP 200,因此請檢視 overlay(或 .next-dev.log),而不是看 HTTP 狀態碼。Overlay 被清空只是判定路由乾淨的一半 —— 另一半是瀏覽器驗證(參見步驟 2)以及該路由順利通過建置。
  • next build —— 僅用於偵測。Build 是 next dev 的權威檢查機制,而不是替代品。請在循環中將其作為每個功能的最後關卡(通過建置是單一路由成功標準的一部分),並作為整個 App 的最終全面驗證。在漸進式流程中,建置也可以在發送 PR 之前,用來確認預先步驟(codemod 已將每個路由排除,且共享的 layout 中不再有同步 IO 阻塞)。在處理路由時,不要用 build 替代 dev loop —— 成功的編譯無法告訴你哪些內容最終進入了靜態外殼(static shell),哪些內容進行了串流(streamed)。預設情況下,建置會在遇到第一個阻塞路由時停止,因此也不適合用來估算整體工作量。在反覆疊代時,有兩個標誌很有幫助:--debug-build-paths 僅建置你指定的路由(以逗號分隔的相對專案根目錄的檔案路徑 glob 模式,例如 --debug-build-paths="app/admin/**/page.tsx" —— 而非 URL 路徑;--debug-build-paths="app/(marketing)/about/page.tsx" —— 而非 /about--debug-build-paths="app/admin" 匹配不到任何內容,會靜默建置 0 個路由),以及 --debug-prerender 可停用提早退出,使建置在首次預渲染失敗後繼續執行,回報所有阻塞路由,並列印出標明原始檔案與行號的更完整 stack trace。

每個阻塞錯誤都有對應的文件頁面 —— 請開啟它。Dev overlay 和建置終端機在列印每個錯誤時,都會附帶 https://nextjs.org/docs/messages/<slug> 連結。該頁面是修復的權威方案指南;行內訊息只是摘要。即便你認為自己已經掌握了某種模式,遇到每一種不同的錯誤時都請抓取該連結 —— 修復方案會持續演進,且相同的錯誤類別根據路由讀取的內容不同,可能會有不同的正確修復方式。切勿僅憑行內訊息即興發揮。(/docs/messages/* 頁面未包含在離線文件中;如果沒有網路,請改為參考 node_modules/next/dist/docs/ 下的各 API 指南,並在回報時說明此限制。)

verifying each fix at runtime

通過建置或清空 overlay 並不能證明路由在執行階段的實際行為符合預期 —— Cache Components 是一個執行階段的機制(帶有串流資料的靜態外殼)。請在每次修復後都進行驗證,而不是只在最後才做。

依偏好順序如下:

  1. next-dev-loop —— 強烈推薦。 透過 agent-browser 交叉比對 /_next/mcp 與實態瀏覽器,一次性浮現編譯與執行階段的問題。其診斷資訊(React 樹、Suspense 邊界、console + network)比手動測試 next dev 更豐富。

    在開始主循環前請先安裝它。不要等到遇到 next dev 單獨無法解釋的問題時才安裝。執行:

    npx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop
    

    該 Skill 會說明所需的 agent-browser 版本,並引導你完成設定。

    需要 Turbopack。 如果 package.jsondev 腳本傳遞了 --webpack,請向使用者提出,並詢問是否有保留 webpack 的原因。如果沒有,請切換至 Turbopack(Next.js 16.3+ 的預設值)。如果使用者希望保留 webpack,請跳過此安裝,改用僅限建置的循環(build-only loop)

    你不需要特別取得權限即可安裝 next-dev-loop 本身。它是一個工具,就像安裝開發依賴項目一樣。如果使用者在線上,請簡短告知你正為了驗證而安裝它。