next-partial-prefetching-adoption
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesenext-partial-prefetching-adoption
Next.js Partial Prefetching 适配实施
Enable Partial Prefetching and walk the app until every link reuses a shared App Shell. This skill sequences the work; per-insight recipes live in the dev overlay fix cards and their docs pages. The Adopting Partial Prefetching guide is the canonical reference for the concepts this skill applies.
The one thing that shapes everything below: these insights surface only in , in the dev overlay's Insights tab. Nothing fails the build. There is no build-only fallback loop for this skill — the work is a sweep of the running app in the browser. If you can't drive a browser, stop and tell the user what you can't verify, or commit the milestone you've reached and hand off.
next devTalk to the user in terms of what they'll see — PRs, features, and how the app behaves after — never the insight slugs or step labels. Before you start, tell them briefly what Partial Prefetching changes: a loads a shared App Shell, and no longer prefetches everything the old full prefetch did.
<Link>prefetch={true}启用Partial Prefetching功能,并遍历应用直至所有链接都能复用共享的App Shell。本技能会规划实施步骤;针对各洞察问题的解决方案可在开发覆盖层的修复卡片及其文档页面中找到。Partial Prefetching 适配指南是本技能所涉概念的权威参考资料。
以下所有内容的核心前提:这些洞察信息仅会在模式下的开发覆盖层Insights标签页中显示。 该功能不会导致构建失败。本技能没有仅针对构建的回退流程——所有操作都需要在浏览器中运行的应用上完成。如果无法操控浏览器,请停止操作并告知用户无法验证的内容,或是提交已完成的里程碑任务后移交工作。
next dev与用户沟通时,要聚焦于他们能看到的内容——PR、功能以及应用调整后的表现——绝不要提及洞察信息的标识或步骤标签。开始前,简要告知用户Partial Prefetching带来的变化:会加载共享的App Shell,且不再像旧版全预取那样预取所有内容。
<Link>prefetch={true}requires
前置要求
-
Cache Components already adopted.only works with
partialPrefetching, and the sweep below assumes the app has no blocking-route errors left: a route whose static shell fails validation surfaces the blocking-prerender error instead of the prefetch insight, so unfinished adoption hides exactly the signal this skill works from. RuncacheComponents: trueto completion first — this skill is its follow-up.next-cache-components-adoption -
Next.js 16.3 or later., the
partialPrefetchingroute segment config, and the prefetch insights all land there.prefetch -
A browser you can drive. Installbefore starting (
next-dev-loop). Link prefetches fire when a link renders and enters the viewport, and shell validation fires on navigation — neither is reachable fromnpx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loopor the build. If the app is webpack-pinned, drive a browser directly (curl, Playwright) — you lose the framework cross-checks, not the insights; they're still in the overlay and the dev log.agent-browser
-
已完成Cache Components适配。仅在
partialPrefetching的情况下生效,且后续的遍历操作假设应用已无阻塞路由错误:若某路由的静态Shell验证失败,会触发blocking-prerender错误而非预取洞察信息,未完成的适配会恰好隐藏本技能依赖的信号。请先完整执行cacheComponents: true——本技能是其后续步骤。next-cache-components-adoption -
Next.js 16.3及以上版本。、
partialPrefetching路由段配置以及预取洞察信息均在该版本中推出。prefetch -
可操控的浏览器。开始前请安装(执行
next-dev-loop)。链接预取会在链接渲染并进入视口时触发,Shell验证会在导航时触发——这两者都无法通过npx skills add https://github.com/vercel/next.js/tree/canary/skills/next-dev-loop或构建流程触发。如果应用固定使用webpack,请直接操控浏览器(如curl、Playwright)——虽然会失去框架交叉检查,但洞察信息仍会显示在覆盖层和开发日志中。agent-browser
notes
注意事项
-
Offline docs. Guide links have offline copies under(bundled since Next.js 16.2), with the directory layout numbered for ordering (e.g.
node_modules/next/dist/docs/). If you can't predict the numbered prefix,node_modules/next/dist/docs/01-app/02-guides/adopting-partial-prefetching.mdresolves it. Thefind node_modules/next/dist/docs -name '<slug>.md'error pages are not bundled./docs/messages/* -
Older versions without bundled docs. Suggestto the user before starting: it downloads a version-matched copy to
npx @next/codemod@latest agents-mdand writes an index into.next-docs//AGENTS.md. It touches files in their repo, so ask first and run it only if they want it.CLAUDE.md
-
离线文档。指南链接的离线副本位于(自Next.js 16.2起捆绑),目录结构按编号排序(例如
node_modules/next/dist/docs/)。如果无法预测编号前缀,可通过node_modules/next/dist/docs/01-app/02-guides/adopting-partial-prefetching.md查找。find node_modules/next/dist/docs -name '<slug>.md'错误页面未被捆绑。/docs/messages/* -
无捆绑文档的旧版本。建议用户在开始前执行:该命令会下载与版本匹配的文档副本至
npx @next/codemod@latest agents-md,并将索引写入.next-docs//AGENTS.md。该操作会修改仓库中的文件,请先征得用户同意,仅在用户需要时执行。CLAUDE.md
background
背景知识
Adopting Partial Prefetching means every route still delivers what its links prefetched before, now split between the App Shell (static and cached content) and the per-link runtime data behind . The guide is the canonical reference for what a prefetch contains and how to decide each case; this skill sequences that work against a running app.
prefetch = 'allow-runtime'适配Partial Prefetching意味着每个路由仍能提供其链接之前预取的内容,只是现在将内容拆分为App Shell(静态缓存内容)和背后的每个链接运行时数据。指南是关于预取内容构成及各场景决策的权威参考;本技能会针对运行中的应用规划该适配工作的流程。
prefetch = 'allow-runtime'working surfaces
操作场景
- The dev server terminal — your primary record. Each validated route's insights are logged as lines with the
Error: Route "...": Next.js encountered ...link. Tail the dev log during the sweep; it's the greppable record of what fired where, and it works the same on Turbopack and webpack.https://nextjs.org/docs/messages/<slug> - The dev overlay Insights tab. Insights are the amber, non-blocking tab. It appears only once an insight has fired, so a route that surfaces nothing shows no tab at all — that's the clean state, not a missing feature. Don't hunt for the tab on a quiet route; confirm clean from the dev log above, which is the reliable signal. The precondition is no blocking-prerender errors — those replace the insight on their route (see requires). An unrelated Issue (a hydration error, a console error) doesn't block the sweep; don't stall on it. When the tab is present, the overlay pill shows the count and each insight has fix cards linking its docs page. The overlay renders inside a shadow root (), so accessibility-tree snapshots don't see it — evaluate into
nextjs-portalwhen you need to read or click it programmatically.shadowRoot - to drive navigations and read the overlay. Prefer it over hand-rolled browser automation for the same reasons as in the Cache Components skill (webpack apps: see requires).
next-dev-loop
Every insight has a docs page — open it. Fetch the linked page for every distinct insight you encounter; the inline message is a summary, the page is the recipe.
- 开发服务器终端——主要记录工具。每个已验证路由的洞察信息会以的形式记录在日志中,并附带
Error: Route "...": Next.js encountered ...链接。遍历时请跟踪开发日志;这是可检索的触发记录,在Turbopack和webpack上的表现一致。https://nextjs.org/docs/messages/<slug> - 开发覆盖层Insights标签页。洞察信息显示在琥珀色的非阻塞标签页中。只有在触发洞察信息后才会显示该标签页,因此无问题的路由不会显示标签页——这是正常状态,并非功能缺失。无需在无问题的路由上寻找标签页;请通过上述开发日志确认状态,这是可靠的信号。前置要求是无blocking-prerender错误——此类错误会替代对应路由上的洞察信息(见前置要求)。无关问题(如水合错误、控制台错误)不会阻碍遍历;无需在此类问题上停滞。当标签页存在时,覆盖层的提示会显示数量,每个洞察信息都有指向其文档页面的修复卡片。覆盖层渲染在shadow root()内,因此可访问性树快照无法识别它——如需以编程方式读取或点击,请访问
nextjs-portal。shadowRoot - :用于驱动导航并读取覆盖层内容。与手动编写浏览器自动化脚本相比,优先使用该工具,原因与Cache Components技能相同(webpack应用:见前置要求)。
next-dev-loop
每个洞察信息都有对应的文档页面——请打开查看。针对遇到的每个独特洞察信息,获取其链接页面;内嵌消息仅为摘要,文档页面才是完整的解决方案。
step 1: audit <Link prefetch={true}>
(before enabling)
<Link prefetch={true}>步骤1:审核<Link prefetch={true}>
(启用前)
<Link prefetch={true}>If is already set in , the app is adopted — skip to step 3. Otherwise work the audit with the global flag off, adopting each destination with — enabling the flag first would mark every route adopted and silence the insight this audit runs on. Ask the user how to ship it, in the language of PRs:
partialPrefetching: truenext.config.tsexport const prefetch = 'partial'link-prefetch-partial- One branch — the whole audit in one change, with the flag enabled and the codemod run at the end (step 2).
- Route by route — each adopted destination ships as its own PR. The insight still fires for the destinations you haven't reached, a live worklist, and step 2 comes after the last one.
The work is identical either way — only the commit boundaries differ. Default by app size: one branch for a handful of links, route by route when the audit is big enough that reviewers need smaller diffs. Note the choice in your report.
Enumerate the links across the whole source tree, not only — they often live in or shared UI packages: , then keep the and bare prop matches (a bare prop is ) and drop and other values. If nothing matches, check for a custom link wrapper before calling the audit empty — grep for , and if a wrapper sets internally or forwards it under another prop name, audit its call sites the same way. If there's still nothing, say so in your report and move on to step 2.
app/src/componentsgrep -rnE '\bprefetch\b' --include='*.tsx' --include='*.jsx' .prefetch={true}prefetchtrueprefetch={false}from 'next/link'prefetch={true}Then, for each one:
-
Click it in. The insight fires at navigation time, not when the link prefetches, so a link sitting in the viewport won't trip it — you have to navigate through it.
next dev -
Adopt the destination. Add. That clears the insight for every link pointing at it. If the route reads URL data (
export const prefetch = 'partial',params), it's a runtime-prefetch candidate for step 5 — keepsearchParamson its links and mark the route:prefetch={true}tsx// TODO(runtime-prefetch): assess with the user (prefetch = 'allow-runtime') export const prefetch = 'partial'Use that exact prefix so step 5 can grep them back. Don't cache or decide anything for these routes now. -
Preserve what that prefetch delivered. The guide's audit table is the canonical decision — fetch it and apply the matching row rather than re-deriving it. Caching uncached content is the judgment call in that table: trace where the data comes from and what freshness and revalidation it needs, per thedocs, and ask the user when the answer isn't clear-cut. The URL-data routes you marked in the previous item wait for step 5.
use cache
如果中已设置,则应用已完成适配——直接跳至步骤3。否则,请在全局配置项关闭的情况下执行审核,通过适配每个目标路由——若先启用配置项,会标记所有路由已适配,并使本审核依赖的洞察信息失效。请用PR相关的术语询问用户交付方式:
next.config.tspartialPrefetching: trueexport const prefetch = 'partial'link-prefetch-partial- 单分支:一次性完成所有审核,最后启用配置项并运行代码转换工具(步骤2)。
- 逐路由:每个适配的目标路由作为独立PR交付。未处理的目标路由仍会触发洞察信息,形成实时任务列表,步骤2在最后一个路由处理完成后执行。
两种方式的操作内容完全相同——仅提交边界不同。默认根据应用规模选择:链接数量较少时使用单分支,当审核内容过多、评审需要更小的差异时使用逐路由方式。请在报告中记录选择。
枚举整个源码树中的链接,不仅限于——链接通常位于或共享UI包中:执行,然后保留和裸属性的匹配项(裸属性等价于),排除和其他值。如果无匹配结果,请先检查是否存在自定义链接包装器——搜索,如果包装器内部设置了或通过其他属性转发该值,请以相同方式审核其调用位置。如果仍无结果,请在报告中说明,然后继续步骤2。
app/src/componentsgrep -rnE '\bprefetch\b' --include='*.tsx' --include='*.jsx' .prefetch={true}prefetchtrueprefetch={false}from 'next/link'prefetch={true}然后,针对每个匹配项:
-
在中点击该链接。洞察信息会在导航时触发,而非链接预取时,因此仅位于视口的链接不会触发——必须通过该链接导航。
next dev -
适配目标路由。添加。这会清除指向该路由的所有链接的洞察信息。如果路由读取URL数据(
export const prefetch = 'partial'、params),则它是步骤5的运行时预取候选——保留其链接上的searchParams并标记路由:prefetch={true}tsx// TODO(runtime-prefetch): 与用户评估(prefetch = 'allow-runtime') export const prefetch = 'partial'请使用上述精确前缀,以便步骤5可通过grep找回这些标记。现在无需缓存或为这些路由做任何决策。
step 2: enable the flag
步骤2:启用配置项
Once every audited destination has , finish in two moves.
prefetch = 'partial'-
Enable the flag globally. Setin
partialPrefetching: true(alongsidenext.config.ts). Every route is adopted now, so every link is good.cacheComponents: true -
Strip the redundantexports. Run the first-party
prefetch = 'partial'codemod rather than a text find-and-replace. It removes onlyremove-partial-prefetchand leaves any other value (a deliberateexport const prefetch = 'partial') in place, along with yourprefetch = 'allow-runtime'markers, which wait for step 5.TODO(runtime-prefetch)Use thechannel, not@canary. The@latesttransform isn't in the stableremove-partial-prefetchrelease yet, and@next/codemoderrors with@next/codemod@latest.Invalid transform choicebashnpx @next/codemod@canary remove-partial-prefetch ./appThe codemod refuses to run on a dirty working tree. Commit or stash unrelated work first, or passto let its edits land alongside your WIP. If the codemod isn't available (older--force, sandboxed environment, offline run), reproduce it by hand by removing@next/codemodfrom everyexport const prefetch = 'partial'— leave any otherapp/**/{page,layout}.{js,jsx,ts,tsx}value in place, and leave theprefetchmarkers where they are. Don't hand-edit when the codemod can run.TODO(runtime-prefetch)
一旦所有审核的目标路由都添加了,通过两步完成配置:
prefetch = 'partial'-
全局启用配置项。在中设置
next.config.ts(与partialPrefetching: true并列)。此时所有路由均已适配,所有链接都符合要求。cacheComponents: true -
移除冗余的导出。使用官方的
prefetch = 'partial'代码转换工具,而非文本查找替换。该工具仅移除remove-partial-prefetch,保留其他值(如刻意设置的export const prefetch = 'partial')以及prefetch = 'allow-runtime'标记,这些标记需等待步骤5处理。TODO(runtime-prefetch)请使用通道,而非@canary。@latest转换尚未纳入稳定版remove-partial-prefetch,@next/codemod会提示@next/codemod@latest错误。Invalid transform choicebashnpx @next/codemod@canary remove-partial-prefetch ./app代码转换工具会拒绝在脏工作树中运行。请先提交或暂存无关工作,或传递参数允许其编辑与正在进行的工作共存。如果无法使用代码转换工具(如旧版--force、沙箱环境、离线运行),可手动移除@next/codemod中的app/**/{page,layout}.{js,jsx,ts,tsx}——保留其他export const prefetch = 'partial'值,以及prefetch标记。当代码转换工具可用时,请勿手动编辑。TODO(runtime-prefetch)
step 3: sweep for URL-data insights (after enabling)
步骤3:排查URL数据洞察信息(启用后)
This is a dev-only second pass. The shell check runs only with the flag on, fires at navigation time, and never blocks the build, so it can happen any time after step 2. The work is one loop — build a route queue from a concrete source (the last route table, or the tree), keep it as a todo list, and load every route in until the queue is empty.
next buildapp/next devWatch the Insights tab and the dev log for lines. The signal this step adds is : a or read outside ties the shared shell to one URL. It can surface even inside an existing when the boundary sits above the read. Open its docs page and follow the fix there.
Next.js encountered … dataURL dataparamssearchParams<Suspense><Suspense>If Cache Components adoption left gaps, loading routes can also re-surface the blocking-prerender errors from that step — (/) or (an uncached /DB call). Those aren't Partial Prefetching insights; treat them as unfinished Cache Components work and fix them the same way.
runtime datacookies()headers()uncached datafetchThese fixes rarely involve the user — each insight names the offending read and its docs page has the fix, so apply it and keep sweeping. Collect the rare exceptions for one batched question at the end: a page that is entirely one URL-dependent region (wrapping it all leaves an empty shell), or a route that should arguably stay opted out. Don't narrate the refactor with comments — the boundaries speak for themselves.
<Suspense>这是仅针对开发环境的二次检查。Shell检查仅在配置项开启时运行,在导航时触发,且绝不会阻塞构建,因此可在步骤2之后的任意时间执行。操作流程为:从具体来源(上一次的路由表或目录树)构建路由队列,将其作为待办列表,在中加载每个路由直至队列为空。
next buildapp/next dev观察Insights标签页和开发日志中的行。本步骤的信号是:在外部读取或会将共享Shell与单个URL绑定。即使在现有内部,若边界位于读取操作上方,也会触发该洞察信息。请打开其文档页面并按照解决方案修复。
Next.js encountered … dataURL data<Suspense>paramssearchParams<Suspense>如果Cache Components适配存在遗漏,加载路由时可能会重新触发该步骤中的blocking-prerender错误——(/)或(未缓存的/数据库调用)。这些并非Partial Prefetching的洞察信息;应将其视为未完成的Cache Components工作,并以相同方式修复。
runtime datacookies()headers()uncached datafetch这些修复通常无需用户参与——每个洞察信息都会指出违规的读取操作,其文档页面提供了解决方案,因此直接修复并继续排查。将罕见的例外情况收集起来,最后批量询问用户:如某个页面完全是URL依赖区域(将其全部包裹会导致空Shell),或某个路由应明确选择退出。请勿用注释描述重构——边界本身已能说明问题。
<Suspense>step 4: verify
步骤4:验证
Checklist before checking in with the user:
- An empty sweep is the expected outcome when Cache Components adoption finished cleanly — the prereq already forced every /
params/searchParamsread behindcookies()(surfaced there as<Suspense>errors), so a quiet log is success, not a missing signal. Any entry still in the Insights tab is a deliberate, documented decision. To confirm the signal can still fire, checkblocking-prerender-*is on, the version is 16.3 or later, and the dev server was restarted after the config change — or move one URL read back outsidepartialPrefetching, watch validation fire, then revert. Expect the probe to surface the Cache Components<Suspense>error rather than the URL-data insight (the upstream check catches the read first) — either one proves the pipeline is alive.blocking-prerender-runtime - The App Shells are real: for each route you changed, confirm the first paint after a navigation shows the intended shared content, not an empty shell or a stuck fallback. A around the whole page body passes validation with an empty shell, which defeats the point.
<Suspense> - still passes.
next build
Then check in with the user. Speak their language — no insight slugs or step labels.
- What you did: which links you audited, which destinations you adopted, and what each link now prefetches.
- What changed: dropped props, boundaries added, and which routes carry a
use cachemarker for later.TODO(runtime-prefetch) - Demo against a production run. Prefetching is limited in development, so won't show the result — run
next devandnext build, and hand the user that URL.next start - Show, don't tell: drive one link live in the headed browser against the production server, so they see the shared App Shell paint instantly and the URL-specific region stream in. Attach before/after screenshots only when a live browser isn't possible.
- Give them the click-through: a table of each changed route — the link to click, and what to expect after the click (what paints instantly, what streams in) — so they can verify each result themselves.
- The question: "Want to commit this (or open the PR) before we look at which routes should also prefetch their URL-specific content?" Wait for the answer — adoption and runtime prefetching read best as their own changes.
与用户确认前,请完成以下检查清单:
- 若Cache Components适配已完整完成,排查结果为空是预期结果——前置要求已强制所有/
params/searchParams读取操作置于cookies()之后(在Cache Components中表现为<Suspense>错误),因此无日志记录即为成功,并非信号缺失。Insights标签页中仍存在的条目是经过深思熟虑的文档化决策。为确认信号仍能触发,请检查blocking-prerender-*已开启、版本为16.3及以上,且配置更改后已重启开发服务器——或将一个URL读取操作移回partialPrefetching外部,观察验证触发,然后恢复。预期该测试会触发Cache Components的<Suspense>错误而非URL数据洞察信息(上游检查会先捕获读取操作)——无论哪种情况都能证明流程正常。blocking-prerender-runtime - App Shell真实有效:针对每个修改的路由,确认导航后的首次渲染显示预期的共享内容,而非空Shell或停滞的回退状态。将整个页面主体包裹在中虽能通过验证,但会导致空Shell,违背了该功能的初衷。
<Suspense> - 仍能通过。
next build
然后与用户确认。使用用户熟悉的语言——不要提及洞察信息标识或步骤标签。
- 你所做的工作:审核了哪些链接、适配了哪些目标路由,以及每个链接现在预取的内容。
- 发生的变化:移除的属性、添加的边界,以及哪些路由带有
use cache标记待后续处理。TODO(runtime-prefetch) - 针对生产环境运行进行演示。预取在开发环境中受限,因此不会显示结果——请运行
next dev和next build,并将URL提供给用户。next start - 演示而非描述:在有界面的浏览器中针对生产服务器点击一个链接,让用户看到共享App Shell立即渲染,URL特定区域流式加载。只有在无法使用实时浏览器时才附上前后截图。
- 提供验证指南:制作一张修改路由的表格——包含点击链接和点击后的预期结果(立即渲染的内容、流式加载的内容),以便用户自行验证每个结果。
- 询问用户:“在我们查看哪些路由还应预取其URL特定内容之前,是否要提交此更改(或打开PR)?”等待用户答复——适配和运行时预取作为独立更改会更清晰。
step 5: runtime prefetching (optional)
步骤5:运行时预取(可选)
The audit marked the candidates instead of deciding them. Grep for and walk the list with the user in one conversation. The question per route is whether they want the URL-dependent content prefetched ahead of the click, or streaming in after navigation is fine. A runtime prefetch costs a server invocation per prefetchable link — the guide's per-link prefetching trade-offs section is the checklist. Don't make these calls alone.
TODO(runtime-prefetch)Where the answer is yes, follow the runtime prefetching guide — add to the route (the codemod in step 2 already stripped the export) and cache the content behind the read using the guide's patterns ( with the runtime value passed in, or for per-user data). Where it's no, delete the marker and leave the route on the default. Either way no marker survives this step. Confirm the opted-in routes against a production run ( and — the runtime prefetch fires there, not in ), give the user the same click-through for them, and keep this as its own commit or PR.
export const prefetch = 'allow-runtime''partial'use cacheuse cache: privateTODO(runtime-prefetch)next buildnext startnext dev审核阶段仅标记了候选路由,未做决策。搜索并与用户逐一讨论列表中的路由。针对每个路由的问题是:是否希望URL依赖内容在点击前预取,还是导航后流式加载即可。运行时预取会为每个可预取的链接触发一次服务器调用——指南中的逐链接预取权衡部分是决策清单。请勿自行做出这些决策。
TODO(runtime-prefetch)若答案为是,请遵循运行时预取指南——为路由添加(步骤2中的代码转换工具已移除导出),并使用指南中的模式缓存读取操作背后的内容(传入运行时值的,或针对用户数据使用)。若答案为否,请删除标记,保留路由默认设置。无论哪种情况,标记都不应在本步骤后残留。针对已选择加入的路由,在生产环境运行中确认(和——运行时预取在该环境中触发,而非),为用户提供相同的验证指南,并将此作为独立的提交或PR。
export const prefetch = 'allow-runtime''partial'use cacheuse cache: privateTODO(runtime-prefetch)next buildnext startnext devfurther reading
扩展阅读
- Instant navigation — the broader validation model and loading-state tooling.
- Prevent regressions with e2e tests — the
@next/playwrighthelper locks in what a navigation shows immediately; recommend it once the sweep is clean, since nothing else guards these in CI.instant() - — grows each route's static shell so the App Shell carries more.
next-cache-components-optimizer
- 即时导航——更广泛的验证模型和加载状态工具。
- 用端到端测试防止回归——的
@next/playwright助手可锁定导航立即显示的内容;建议在排查完成后使用该工具,因为CI中没有其他机制能保障这些内容。instant() - ——扩展每个路由的静态Shell,使App Shell承载更多内容。
next-cache-components-optimizer