cloudflare / cloudflare/vinext

Link `prefetch` default behavior change under Partial Prefetching: App Shell only

Open
#1,820 0 comments 0 reactions 0 assignees View on GitHub
nextjs-tracking
Dominant language
TypeScript
Stars
8.8k
Forks
406
Avg merge
2d 6h
Merged PRs (30d)
120

Description

## Next.js Change

**Commit:** [`16b44a8`](https://github.com/vercel/next.js/commit/16b44a85bebc3b8ade938e8e4b9dbd05ab1ab1ff)
**PR:** [#94510](https://github.com/vercel/next.js/pull/94510)

## What changed

When Partial Prefetching is enabled (`partialPrefetching: true` globally or `unstable_prefetch = 'partial'` per-segment, see #1819), this changes the default behavior of ``:

- **Before:** `` without an explicit `prefetch` prop would prefetch in partial mode; `` would prefetch the entire page (including dynamic data).
- **After:** `` with no `prefetch` prop only prefetches the **App Shell** of the target page — not page data. Per-page data is only prefetched when `prefetch={true}` is explicitly set.

### Behavior by route type (when Partial Prefetching is enabled)

- **Dynamic / partially static routes:** Links never include page content unless `prefetch={true}` is set; only the App Shell defined by `loading.tsx` is prefetched. Roughly matches pre-Cache-Components behavior.
- **Fully static routes:** **Significant behavior change.** Previously, the entire static page was prefetched regardless of `prefetch` prop. Now, content-heavy sites (blogs, docs) need to set `prefetch={true}` to retain the previous behavior.

### Migration aid

A new `unstable_prefetch = 'unstable_eager'` segment opt-in (and `partialPrefetching: 'unstable_eager'` global mode) forces every `` to a given route to behave as if `prefetch={true}` was set. This restores the pre-Partial-Prefetching behavior for that route. Not recommended outside migration scenarios.

### Files changed (non-test)

- `packages/next/src/build/segment-config/app/app-segment-config.ts`
- `packages/next/src/client/components/segment-cache/scheduler.ts` — `+52/-7`, the core prefetch-mode decision
- `packages/next/src/server/app-render/create-flight-router-state-from-loader-tree.ts`
- `packages/next/src/server/config-schema.ts`, `config-shared.ts`
- `packages/next/src/shared/lib/app-router-types.ts`

## Impact on vinext

vinext's `next/link` shim and prefetch logic do not currently implement Partial Prefetching or the segment-cache scheduler (tracked in #1614). When/if vinext implements those, the default behavior of `` under Partial Prefetching must follow the new semantics:

1. **Implicit prefetch (no `prefetch` prop) under Partial Prefetching** → App Shell only, not page data.
2. **`prefetch={true}` under Partial Prefetching** → prefetch the full Cache Components payload (still excludes dynamic data; that is the existing Partial Prefetching definition).
3. **`unstable_eager` segments** → treat every `` to that route as if `prefetch={true}` was set.
4. **Fully static routes under Partial Prefetching** → no longer eagerly prefetched by default. Document this as a behavioral change in any vinext Partial Prefetching adoption guide.

This is also a documentation-impact change: anyone adopting `partialPrefetching` on a content-heavy site (blogs, docs — including the `nextra-docs-template` example) needs to know that link-following will feel slower unless they opt in to eager mode or set `prefetch={true}` explicitly.

## Related

- #1819 — `partialPrefetching` global config + `unstable_prefetch = 'partial'` segment opt-in
- #849 — `unstable_prefetch` segment config baseline
- #1614 — Client-side App Shell prefetching infrastructure

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.