Partial Prefetching: Default to App Shell only (#94510)
When Partial Prefetching is enabled (unstable_prefetch = 'partial'),
this changes the default behavior of Link to only prefetch the App Shell
of the target page, not the page data. Per-page data is only prefetched
if the Link's `prefetch` prop is set to `true`.
For dynamic/partially static pages, this roughly matches the pre-Cache
Components behavior: links to those pages never include page content,
only a reusable App Shell defined by `loading.tsx` (if defined).
For fully static pages, this is a significant behavior change: the prior
behavior of Next.js was to prefetch the entire static page, regardless
of whether `prefetch={true}` was set. As a default behavior, this made
sense for certain kinds of content-heavy sites, like blogs, where most
of the content is expected to be generated at build time. These apps
will now need to set the prefetch prop to `true` to maintain the
previous behavior.
The main motivation is to simplify the cost/performance model for
prefetching: rendering a Link is now "free" unless `prefetch={true}` is
set.
I've put "free" in quotes because even if `prefetch={true}` is not set,
Next.js will still prefetch a generic App Shell. However, this App Shell
only needs to be rendered once per filesystem route, as opposed to once
per link. So it's not prefetching in the usual sense that is meant in
the context of SPA-based web applications. It's more like incremental
bundle loading, except instead of loading just the code for the route,
we also load the generic UI.
To aid in incremental adoption of this feature, this also adds an
"eager" prefetch mode that can be set on any layout or page
(unstable_prefetch = 'unstable_eager'). When "eager" is set, every Link
to that route is assigned an implied `prefetch={true}`, restoring the
pre-Partial Prefetching behavior. Blog-like sites may find this useful,
but it's mostly intended to support migrating existing apps.
(For canary testers of Partial Prefetching, you can also enable eager
mode globally by setting `partialPrefetching: 'unstable_eager'`. This is
not recommended except for migration purposes, even for blog-like
sites.)
<!-- NEXT_JS_LLM_PR -->