next-cache-components-adoption
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesenext-cache-components-adoption
Next.js缓存组件适配指南
Enable Cache Components on an app and walk it to a clean build. This skill sequences the work; per-error recipes live in the dev overlay fix cards, stack traces, and pages.
/docs/messages/blocking-prerender-*在应用中启用Cache Components并完成无错误构建。本技能按顺序安排工作;针对具体错误的解决方案可在开发覆盖层的修复卡片、堆栈跟踪以及页面中找到。
/docs/messages/blocking-prerender-*requires
前置要求
App Router only. Cache Components is an App Router feature; does nothing for routes. If the project has a or tree but no or tree, stop and tell the user — Pages → App migration is its own project, not part of this skill. A hybrid app (both and ) is fine: the flag affects the routes; routes are unaffected and don't need opt-outs.
cacheComponents: truepages/pages/src/pages/app/src/app/pages/app/app/pages/Next.js 16.3+. That release is where the pieces this skill relies on land: top-level , , the dev-overlay instant-navigation validation warnings (including ), and the codemod.
cacheComponentsexport const instantlink-prefetch-partialcache-components-instant-falseIf reports below 16.3, upgrade first:
next --version- to apply the version-to-version codemods.
npx @next/codemod@latest upgrade latest - Read the relevant version upgrade guide (e.g. Version 16) for what the codemod doesn't cover.
This skill also assumes a clean starting point. If the app still uses / , route segment configs (, , ), or , work those out first via the migration guide, then come back here.
experimental.dynamicIOexperimental.useCachedynamicrevalidatefetchCacheunstable_cache()If the app already uses , there is no green build before — the pre-flag build errors with . Enabling the flag is the first step of milestone A, not a thing to do after getting green; the green baseline comes from milestone A (blanket the opt-outs in), not from before it. Note this in your starting summary so it doesn't read as a regression.
"use cache"cacheComponents: trueplease enable the feature flag cacheComponentsOffline copies of guide links live under , with the directory layout numbered for ordering (e.g. ). The trailing filename matches the slug. If you can't predict the numbered prefix, resolves it. The error pages are not bundled. If offline docs are missing entirely, run to write a version-matched index into / .
node_modules/next/dist/docs/node_modules/next/dist/docs/01-app/02-guides/migrating-to-cache-components.mdfind node_modules/next/dist/docs -name '<slug>.md'/docs/messages/*npx @next/codemod@latest agents-mdAGENTS.mdCLAUDE.md仅支持App Router。Cache Components是App Router的功能;对路由无效。如果项目包含或目录树,但没有或目录树,请告知用户——从Pages Router迁移到App Router是独立项目,不属于本技能的范畴。混合应用(同时包含和)是允许的:该标志仅影响路由;路由不受影响,无需排除。
cacheComponents: truepages/pages/src/pages/app/src/app/pages/app/app/pages/Next.js 16.3+。该版本包含本技能依赖的所有功能:顶层配置、、开发覆盖层的即时导航验证警告(包括),以及代码转换工具。
cacheComponentsexport const instantlink-prefetch-partialcache-components-instant-false如果显示版本低于16.3,请先升级:
next --version本技能还假设项目处于干净的起始状态。如果应用仍在使用 / 、路由段配置(、、)或,请先通过迁移指南处理这些内容,然后再回到本技能。
experimental.dynamicIOexperimental.useCachedynamicrevalidatefetchCacheunstable_cache()如果应用已使用,那么在设置之前无法构建成功——设置标志前的构建会报错。启用该标志是里程碑A的第一步,而不是在构建成功后再做的事;绿色基线来自里程碑A(全面添加排除配置),而不是之前的状态。请在起始总结中注明这一点,避免被视为回归问题。
"use cache"cacheComponents: trueplease enable the feature flag cacheComponents指南链接的离线副本位于目录下,目录结构按编号排序(例如)。文件名后缀与slug匹配。如果无法预测编号前缀,可以运行来查找。错误页面未被打包。如果完全缺少离线文档,可以运行将匹配版本的索引写入 / 。
node_modules/next/dist/docs/node_modules/next/dist/docs/01-app/02-guides/migrating-to-cache-components.mdfind node_modules/next/dist/docs -name '<slug>.md'/docs/messages/*npx @next/codemod@latest agents-mdAGENTS.mdCLAUDE.mdthe shape of the work
工作流程
Adoption has two milestones. Each is shippable on its own:
- A. Green build. passes with
next build— blanketcacheComponents: trueif needed. Setup for B. (steps 1–2.)instant = false - B. Remove . This is the loop where adoption happens. Walk the route tree top-down, one subtree at a time, removing each opt-out and either making the route prerenderable or documenting it as a deliberate Block — checking in with the user at each subtree boundary. Expect to spend most of the time here. (steps 2–3.)
instant = false
Adoption is complete after B. Further optimization — making navigations instant, adopting Partial Prefetching, locking the result in with e2e tests, growing static shells — is covered by the linked guides in further reading. Point the user at them; this skill doesn't walk through them.
End of every milestone: summarize and ask. Tell the user which routes changed and how (cached / wrapped in / opted out as a documented Block), what they should sanity-check, and ask whether to open a PR before continuing. Each milestone is a real checkpoint, not a step inside one agent run. Don't silently roll on.
<Suspense>适配过程分为两个里程碑,每个里程碑的成果都可独立发布:
- A. 无错误构建。设置后
cacheComponents: true执行成功——必要时全面添加next build配置。为里程碑B做准备(步骤1-2)。instant = false - B. 移除配置。这是完成适配的核心环节。自上而下遍历路由树,每次处理一个子树,移除每个排除配置,要么使路由可预渲染,要么将其标记为故意阻塞并记录——在每个子树边界处与用户确认。预计大部分时间会花费在此环节(步骤2-3)。
instant = false
完成里程碑B即表示适配完成。进一步优化——实现即时导航、采用部分预取、通过端到端测试锁定结果、扩展静态外壳等——可参考延伸阅读中的链接指南。请引导用户查看这些内容;本技能不会详细讲解这些优化步骤。
每个里程碑结束时:总结并确认。告知用户哪些路由发生了变更以及变更方式(缓存/包裹在中/标记为已记录的阻塞路由),他们需要检查哪些内容,并询问是否要在继续之前创建PR。每个里程碑都是真实的检查点,而非单次Agent运行中的一个步骤。不要静默继续。
<Suspense>background
背景知识
cacheComponents: true<Suspense>export const instant = falseinstant = falsenew Date()Date.now()Math.random()crypto.randomUUID()blocking-prerender-current-time-random-cryptoinstant = falsenew Date()cacheComponents: true<Suspense>export const instant = falseinstant = falsenew Date()Date.now()Math.random()crypto.randomUUID()blocking-prerender-current-time-random-cryptoinstant = falsenew Date()surfacing errors
错误排查
Two surfaces; they show different things.
next build--debug-build-paths--debug-build-paths="app/admin/**/page.tsx"--debug-build-paths="app/(marketing)/about/page.tsx"--debug-build-paths=/admin--debug-prerendernext dev.next-dev.logVerifying a fix at runtime. A green build or a cleared overlay isn't proof the route actually behaves — Cache Components is a runtime concern (a static shell with streamed data). Load the route in a real browser, wait for streaming to settle, and confirm it renders. Three ways, in order of preference:
-
Theskill is the fastest path: it cross-checks
next-dev-loopagainst the live browser. Install if your agent doesn't have it:/_next/mcpbashnpx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loopIt has its own hard prerequisites (Turbopack and) and will tell you how to set those up.agent-browser >= 0.27.0 -
A browser you can drive yourself (Playwright, agent-browser, any browser-automation tool).is an accelerator, not a prerequisite.
next-dev-loop -
No browser at all? Ask the user. Either ask them to drive the dev server and report what the overlay shows, or commit the milestone you've reached and hand off. Don't silently stop at A or B and call it done — the runtime behavior won't surface in the build. Be explicit about what you couldn't verify.
Verify after every fix, not only at the end. Don't fall back to grepping source or trusting the build alone.
有两种排查方式,它们显示的内容不同。
next build--debug-build-paths--debug-build-paths="app/admin/**/page.tsx"--debug-build-paths="app/(marketing)/about/page.tsx"--debug-build-paths=/admin--debug-prerendernext dev.next-dev.log在运行时验证修复效果。无错误构建或覆盖层错误清除并不代表路由实际行为正常——Cache Components是运行时相关功能(带有流式数据的静态外壳)。在真实浏览器中加载路由,等待流传输完成,确认渲染正常。以下三种方式按优先级排序:
-
技能是最快的方式:它会交叉校验
next-dev-loop和实时浏览器的内容。如果Agent未安装该技能,请安装:/_next/mcpbashnpx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop它有自己的硬性前置要求(Turbopack和),并会告知如何设置这些要求。agent-browser >= 0.27.0 -
可自行操控的浏览器(Playwright、agent-browser或任何浏览器自动化工具)。是加速工具,不是必需项。
next-dev-loop -
**完全没有浏览器?**询问用户。要么请他们操控开发服务器并报告覆盖层显示的内容,要么提交当前已完成的里程碑并移交。不要在里程碑A或B处静默停止并声称已完成——运行时行为不会在构建中体现。请明确说明无法验证的内容。
每次修复后都要验证,而不仅仅是在最后。不要依赖 grep 源代码或仅信任构建结果。
step 1: choose a strategy
步骤1:选择策略
Ask the user; don't assume. In a non-interactive run (no way to prompt), default to Blanket for a multi-route app and Direct for a single-route or handful-of-routes app, and say so when you start.
- Blanket — run the codemod to opt every page and layout out, get a clean build immediately, merge that, then remove the opt-outs feature by feature in follow-up PRs. Use for large apps, team repos (a long-lived failing branch blocks others), or when you can't land every route in one PR.
- Direct — enable the flag and fix every route in place in one pass. Use for small or solo apps where one PR is realistic.
询问用户,不要假设。在非交互式运行中(无法提示),多路由应用默认选择全面排除策略,单路由或少量路由应用默认选择直接修复策略,并在开始时说明这一点。
- 全面排除——运行代码转换工具将所有页面和布局排除,立即获得干净的构建结果,合并该变更,然后在后续PR中逐个移除排除配置。适用于大型应用、团队仓库(长期失败的分支会阻碍其他人),或无法在一个PR中完成所有路由适配的场景。
- 直接修复——启用标志并一次性就地修复所有路由。适用于小型或个人应用,可通过一个PR完成适配。
blanket
全面排除
bash
npx @next/codemod@canary cache-components-instant-false ./appInserts (with a comment) into every file, skipping files that already declare and any module marked or . Then set . The TODO comments are the work queue for milestone B.
export const instant = false// TODO: Cache Components adoptionapp/**/{page,layout,default}instant"use client""use server"cacheComponents: trueIf the codemod isn't available (older , sandboxed environment, offline run), reproduce it by hand: for every that isn't or and doesn't already declare or export in any form, insert the three-line block below after the file's import statements (or at the top, if there are none):
@next/codemodapp/**/{page,layout,default}.{js,jsx,ts,tsx}"use client""use server"instantts
// TODO: Cache Components adoption. Refactor this route so this opt-out can be removed.
// See: https://nextjs.org/docs/app/guides/migrating-to-cache-components
export const instant = falseThen set . The result is the same as what the codemod produces.
cacheComponents: trueThe codemod opts every segment out, not only the root, on purpose. Resolution is top-down, first-explicit-config-wins: the highest in a route's tree decides the whole subtree, and deeper ones are never read. If you only opted the root layout out, removing it would re-arm validation for the entire app at once. With an opt-out on every segment, removing one segment's opt-out validates only that segment — its descendants keep their own opt-outs and stay green, so the blast radius is one segment at a time.
instant = falseBecause the highest opt-out wins, remove them top-down (root first, then descend). Removing a leaf's opt-out does nothing while an ancestor still holds one.
Confirm milestone A with a build. Run and make sure it completes with no blocking-route errors before you call the green build done. The codemod gets you most of the way, but a shared layout that calls / directly still fails regardless of the opt-out (see "background" above), so the build is the proof, not the codemod run.
next buildnew Date()Math.random()After running the codemod, confirm the root layout got an opt-out (). The root layout is the one segment that must be covered: it renders every route, including framework routes like , so if it still reads without an opt-out the build fails on even though no other route changed. If it was missed, add to it by hand.
grep -n "export const instant" app/layout.*/_not-foundcookies()/_not-foundexport const instant = falseNever add to a synthetic route like — there is no user file for it, and the directive wouldn't apply. When (or another framework route) blocks, the cause is the root layout it renders through; fix the opt-out there.
instant = false/_not-found/_not-foundClient Components ( pages/layouts) get no opt-out — the codemod skips them on purpose. is a Server Component route segment config; exporting it from a client module is a build error (). They don't need one anyway: a client page is covered by its nearest server layout's opt-out, and a client page can't read server request data (, , ) itself, so it rarely blocks on its own. If a route with a client page still blocks, the cause is server-side data in an ancestor layout — fix the opt-out or the read there, not on the client page.
"use client"instantE1344cookies()headers()await paramsbash
npx @next/codemod@canary cache-components-instant-false ./app在每个文件中插入(附带注释),跳过已声明的文件以及标记为或的模块。然后设置。TODO注释是里程碑B的工作队列。
app/**/{page,layout,default}export const instant = false// TODO: Cache Components adoptioninstant"use client""use server"cacheComponents: true如果代码转换工具不可用(版本较旧、沙箱环境、离线运行),可手动实现:对于每个未标记或且未以任何形式声明或导出的文件,在文件的导入语句之后(如果没有导入语句则在顶部)插入以下三行代码:
@next/codemod"use client""use server"instantapp/**/{page,layout,default}.{js,jsx,ts,tsx}ts
// TODO: Cache Components adoption. Refactor this route so this opt-out can be removed.
// See: https://nextjs.org/docs/app/guides/migrating-to-cache-components
export const instant = false然后设置。结果与代码转换工具生成的内容一致。
cacheComponents: true代码转换工具会将每个路由段排除,而非仅根路由段,这是故意设计的。解析是自上而下的,以第一个明确的配置为准:路由树中层级最高的决定整个子树,更深层级的配置不会被读取。如果仅排除根布局,移除它会立即重新启用整个应用的验证。而在每个路由段都设置排除配置后,移除一个路由段的排除配置只会验证该路由段——其子路由段仍保留自己的排除配置并保持构建成功,因此影响范围仅限于单个路由段。
instant = false由于层级最高的排除配置优先级最高,应自上而下移除(先根路由,再子路由)。在祖先路由段仍保留排除配置时,移除叶子路由段的排除配置不会产生任何效果。
通过构建确认里程碑A。运行,确保完成时没有阻塞路由错误,再宣布无错误构建完成。代码转换工具能解决大部分问题,但直接调用 / 的共享布局仍会失败,无论是否设置排除配置(见上文“背景知识”),因此构建结果才是最终证明,而非代码转换工具的运行结果。
next buildnew Date()Math.random()运行代码转换工具后,确认根布局已添加排除配置(运行)。根布局是必须覆盖的路由段:它渲染所有路由,包括等框架路由,因此如果它仍在未设置排除配置的情况下读取,即使其他路由未变更,构建也会在处失败。如果根布局被遗漏,请手动添加。
grep -n "export const instant" app/layout.*/_not-foundcookies()/_not-foundexport const instant = false切勿向等合成路由添加——没有对应的用户文件,该指令也不会生效。当(或其他框架路由)阻塞时,原因是它渲染时经过的根布局;请在根布局中修复排除配置或数据读取问题。
/_not-foundinstant = false/_not-found客户端组件(页面/布局)无需排除配置——代码转换工具会故意跳过它们。是服务端组件的路由段配置;从客户端模块导出它会导致构建错误()。它们也不需要:客户端页面会被最近的服务端布局的排除配置覆盖,且客户端页面本身无法读取服务端请求数据(、、),因此很少会自行阻塞。如果包含客户端页面的路由仍阻塞,原因是祖先布局中的服务端数据;请在祖先布局中修复排除配置或数据读取问题,而非客户端页面。
"use client"instantE1344cookies()headers()await paramsdirect
直接修复
Set and collect the errors. The reported routes are the work queue; there are no opt-outs to remove.
cacheComponents: true设置并收集错误。报告的路由即为工作队列;无需添加排除配置。
cacheComponents: truestep 2: remove opt-outs, one subtree at a time
步骤2:逐个移除排除配置
The route tree is the work queue. Pick one subtree (, or a top-level app if the repo has several — marketing, app, docs), finish it end-to-end, ship it, then start the next. Each subtree is an independent, mergeable change. Don't fan out across the whole app in one pass — the point of milestone A's blanket was to make the loop incremental, not optional.
app/dashboard/**Within a subtree, walk top-down (layouts before the pages beneath them, root layout first). The root layout is often the hardest (it wraps / and frequently reads ), but it shadows every route including framework routes like , so it has to come off before anything below it can be validated. (Direct path: there are no opt-outs to remove — fix each failing route; if a hand-written opt-out on an ancestor shadows it, remove that first.)
<html><body>cookies()/_not-foundA green build mid-walk doesn't mean the layout is clean. Removing a layout's opt-out while its descendant pages still have theirs keeps the build green — each page shadows the inherited validation. The layout's actual blocking reads only surface once nothing below it shadows them. So after a layout is opt-out-free, keep going down the subtree; if the layout has an inherent blocker, the first page you uncover will be the one to surface it. Don't call a subtree done at the layout boundary.
For each route in the subtree:
- Remove its (Blanket) or target the failing route (Direct).
instant = false - Reload it in dev or rebuild only that route. If it's clean, the route was already prerenderable — move on.
- If it still blocks, read the error in the dev overlay and apply the fix it points at. When the call gets ambiguous — you're not sure which fix fits, the blocking code looks security-sensitive, or the user might want to keep the route blocking on purpose — read references/per-page-decisions.md before editing. Those cases are user check-in moments, not agent judgment calls.
- Re-check the route. If your fix touched shared code (a layout, a sidebar component), re-check sibling routes too — a shared-shell change can fix the route you're on and break a sibling. Then move to the next route.
Keep a todo list of the subtree's routes and work it to completion; don't truncate. When every route in the subtree is clean, move to step 3 to verify and hand the subtree off to the user.
路由树即为工作队列。选择一个子树(例如,或仓库中的一个顶级应用——营销、主应用、文档),从头到尾完成适配,发布变更,然后开始下一个子树。每个子树都是独立的、可合并的变更。不要在一次操作中覆盖整个应用——里程碑A的全面排除策略就是为了让这个环节可增量进行,而非可选。
app/dashboard/**在子树中,自上而下遍历(先布局,再其下的页面,先根布局)。根布局通常是最难的(它包裹 / 且经常读取),但它会覆盖所有路由,包括等框架路由,因此必须先移除其排除配置,才能验证其下的任何路由。(直接修复路径:无需移除排除配置——修复每个失败的路由;如果祖先路由段的手动排除配置覆盖了它,先移除该配置。)
<html><body>cookies()/_not-found遍历过程中的无错误构建不代表布局已清理完成。移除布局的排除配置时,如果其子页面仍保留排除配置,构建仍会成功——每个页面都会覆盖继承的验证。只有当布局下没有任何路由段覆盖验证时,布局的实际阻塞读取才会暴露。因此,布局移除排除配置后,继续向下遍历子树;如果布局存在固有阻塞问题,第一个被暴露的页面会显示错误。不要在布局边界处宣布子树适配完成。
对子树中的每个路由:
- 移除其配置(全面排除策略)或定位失败的路由(直接修复策略)。
instant = false - 在开发环境中重新加载路由或仅重新构建该路由。如果无错误,说明路由已可预渲染——继续下一个。
- 如果仍阻塞,请查看开发覆盖层中的错误并应用其指向的修复方案。当情况不明确时——不确定哪种修复方案适用、阻塞代码看起来涉及安全敏感内容,或用户可能希望故意保留路由阻塞——在编辑前请阅读**references/per-page-decisions.md**。这些情况需要与用户确认,而非由Agent自行判断。
- 重新检查路由。如果修复涉及共享代码(布局、侧边栏组件),请同时重新检查兄弟路由——共享外壳的变更可能修复当前路由,但会破坏兄弟路由。然后继续下一个路由。
保留子树路由的待办列表,直到全部完成;不要中途停止。当子树中的所有路由都无错误时,进入步骤3验证并将子树移交用户。
step 3: verify the subtree
步骤3:验证子树
A checklist, not new adoption work. This is where the user signs off on the subtree before you start the next.
- completes without blocking-route errors.
next build - No bare opt-outs are left in the subtree (
// TODO: Cache Components adoptionto confirm). Anygrepleft behind must be a deliberate, documented Block — its comment rewritten to a reason (see references/per-page-decisions.md → "when to leave a Block in place"), not the originalinstant = false.// TODO - Drive each route in dev, not only the build. Visit it, wait for streaming to settle, confirm every fallback resolves to its real content (not stuck on a skeleton or a blank). A green build with zero opt-outs is not the same as a working route. Query the live DOM if a tool's snapshot looks stale before reporting a route as broken.
<Suspense> - Show the user the rendered result. A screenshot or the visible content you observed, per route. The build can't tell whether the streamed-in loading state, the fallback, or the final layout matches what the user wants. Adoption changes the experience, so the person who owns the product should sign off on each piece.
Expect some routes to still print (Dynamic) in the build's route table — that is success, not a regression. A route comes out when it does request-time work through the documented escape hatch (e.g. a layout that for ); the page is no longer opted out, it is genuinely dynamic. Don't rip the escape hatch back out chasing a . The inverse also holds: does not force a route to be . The glyph reflects what the route does at prerender time, not which validation knobs it exports.
ƒƒawait connection()new Date()◐instant = falseƒWhen the subtree passes and the user is happy with each route, summarize and ask: open a PR and move to the next subtree, or stop here?
Milestone B is done only when every subtree is clean — every remaining sits under a reason comment, no bare TODOs are left ( returns nothing). Adoption is complete here. Point the user at further reading if they want to push the experience further, or stop and ship.
instant = falsegrep -rln "TODO: Cache Components adoption" app这是一个检查清单,而非新的适配工作。用户需要在此环节确认子树适配完成,才能开始下一个子树。
- 完成时无阻塞路由错误。
next build - 子树中没有遗留未处理的排除配置(通过
// TODO: Cache Components adoption确认)。任何遗留的grep都必须是故意的、已记录的阻塞路由——其注释需修改为具体原因(见references/per-page-decisions.md → “何时保留阻塞路由”),而非原始的instant = false。// TODO - 在开发环境中访问每个路由,而非仅依赖构建。访问路由,等待流传输完成,确认每个的回退内容都已解析为真实内容(未停留在骨架屏或空白状态)。无错误构建且无排除配置并不代表路由能正常工作。如果工具的快照看起来过时,请查询实时DOM后再报告路由损坏。
<Suspense> - 向用户展示渲染结果。每个路由的截图或你观察到的可见内容。构建无法判断流式加载状态、回退内容或最终布局是否符合用户预期。适配会改变用户体验,因此产品负责人应确认每个部分。
部分路由在构建的路由表中仍显示(动态)是正常的,而非回归问题。当路由通过已记录的逃逸舱口执行请求时工作(例如布局通过获取),路由会显示为;页面不再被排除,而是真正的动态路由。不要为了追求而移除逃逸舱口。反之亦然:不会强制路由显示为。该符号反映的是路由在预渲染时的行为,而非其导出的验证配置。
ƒawait connection()new Date()ƒ◐instant = falseƒ当子树通过验证且用户对每个路由都满意时,总结并确认:创建PR并开始下一个子树,还是在此停止?
只有当每个子树都清理完成——所有遗留的都带有原因注释,没有未处理的TODO(无返回结果)——里程碑B才算完成。适配在此处完成。如果用户想要进一步优化体验,请引导他们查看延伸阅读,或停止并发布。
instant = falsegrep -rln "TODO: Cache Components adoption" appfurther reading
延伸阅读
Adoption ends at milestone B. The work below is optional and lives in the docs — link the user to them and let them decide which to take on next. Don't walk these through inside this skill.
- Instant navigation — dev-only validation warnings the overlay raises on client navigation. Same shape as the blocking-prerender errors you cleared in step 2; the guide covers the per-warning details. Recommend it next if the user wants navigations to actually be instant (a green build doesn't guarantee that — a above the shared layout caught the page-load case but doesn't cover client navigation).
<Suspense> - Adopting Partial Prefetching — walks an audit of calls driven by the dev overlay's
<Link prefetch={true}>warning, then flips thelink-prefetch-partialconfig. Walk the audit first, with the flag off — flipping it before the audit makes every route count as adopted, so the warnings never fire and the per-link signal is lost. The biggest payoff of Cache Components:partialPrefetchingprefetches only the static App Shell by default. Recommended after instant navigation, since its fixes feed directly into how much of each route the shell can prefetch.<Link> - Prefetching and Runtime prefetching — broader prefetching reference. Runtime prefetching extends the static shell with per-session content; reach for it when a route's shell is too thin to be useful and Partial Prefetching alone doesn't cover the gap.
- Locking the result in with e2e tests — the
@next/playwrighthelper asserts on the UI that's available immediately on navigation, so regressions surface in CI. Recommend it once a route is instant:instant()confirms it now; annext-dev-looptest keeps it that way.instant() - — a separate skill that grows each route's static shell so more of the page prerenders and less streams in. Pure optimization, not part of adoption.
next-cache-components-optimizer
适配在里程碑B结束。以下工作是可选的,相关内容在文档中——引导用户查看这些链接,让他们决定下一步要做什么。本技能不会详细讲解这些步骤。
- 即时导航——开发环境中覆盖层在客户端导航时发出的验证警告。与步骤2中清除的阻塞预渲染错误格式相同;指南包含针对每个警告的详细内容。如果用户希望导航真正实现即时,建议接下来查看该指南(无错误构建不保证这一点——共享布局上方的处理了页面加载场景,但不覆盖客户端导航)。
<Suspense> - 采用部分预取——根据开发覆盖层的警告,审核
link-prefetch-partial调用,然后设置<Link prefetch={true}>配置。先审核,再启用标志——在审核前启用标志会使所有路由被视为已适配,警告不会触发,从而丢失每个链接的信号。Cache Components最大的优势:partialPrefetching默认仅预取静态应用外壳。建议在完成即时导航后查看,因为其修复内容直接影响外壳可预取的路由内容量。<Link> - 预取和运行时预取——更全面的预取参考文档。运行时预取会将静态外壳扩展为包含会话内容;当路由外壳过于单薄且部分预取无法覆盖差距时,可使用该功能。
- 通过端到端测试锁定结果——的
@next/playwright助手会断言导航时立即显示的UI,因此回归问题会在CI中暴露。建议在路由实现即时导航后使用:instant()确认当前状态;next-dev-loop测试保持该状态。instant() - ——一个独立技能,用于扩展每个路由的静态外壳,使更多页面内容可预渲染,减少流式传输内容。这是纯优化,不属于适配范畴。
next-cache-components-optimizer