Skip to content

[pull] canary from vercel:canary#1118

Merged
pull[bot] merged 2 commits into
code:canaryfrom
vercel:canary
Jun 10, 2026
Merged

[pull] canary from vercel:canary#1118
pull[bot] merged 2 commits into
code:canaryfrom
vercel:canary

Conversation

@pull

@pull pull Bot commented Jun 10, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

unstubbable and others added 2 commits June 10, 2026 18:12
When the streaming dev render defers a short-lived `'use cache'` entry
to a later stage (a `revalidate` of zero or a short `expire` excludes it
from the static shell, a short `stale` time excludes it from the runtime
prefetch shell), it previously left the cache signal read open. At a
staged rendering task boundary that open read looked like a pending
cache read, so even a warm handler hit was counted as a cache miss,
lighting the cold-cache indicator and routing validation through the
background warm render. We now end the cache signal read as soon as such
an entry is deferred, the same as the prerender path already does, and
serve the buffered value through a plain stream instead of one tracked
by the cache signal, so a warm short-lived hit is no longer mistaken for
a miss. A deferred entry can still turn out to be stale and need
regenerating (for instance, a cache handler may return a past-`expire`
entry), so the regenerate path re-begins the read before generating,
keeping the signal balanced against the regeneration's own end of the
read rather than over-decrementing it.

The runtime-prefetch exclusion for a short stale time must only apply
when the render actually produces the runtime prefetch shell, which is a
property of the request rather than the cache entry. An initial HTML
load, a plain client navigation, and an HMR refresh all produce the
static shell, where a short-stale entry stays, mirroring the static
prerender. A client navigation into a runtime-prefetch route produces
the runtime prefetch shell, where it is excluded, mirroring the
`prerender-runtime` prerender. We thread the render's shell stage onto
the request store, and onto the warm validation render that mirrors it,
and gate the stale-based deferral on `shellStage === Runtime`. This
preserves the build-time asymmetry where a short stale time is omitted
from the runtime prefetch but not from the static shell.

A new `short-stale-cache` fixture and warmup test exercise this
asymmetry directly: a `'use cache'` entry with a short stale time but a
long expire resolves in the static stage on an initial load and on a
navigation without runtime prefetch, and only resolves dynamically on a
navigation into a runtime-prefetch route. The previously skipped
short-lived warmup case is re-enabled, and the cache-indicator
short-lived case now asserts the cold-cache badge on a cold load but not
on a warm reload. Those fixtures use a long `revalidate` so the entry
stays a fresh hit for the duration of the test, isolating them from the
in-memory handler dropping the entry at `revalidate`; that workaround
can be dropped once the cache handler serves stale entries in dev.
x-ref to next/root-params from the i18n guide
@pull pull Bot locked and limited conversation to collaborators Jun 10, 2026
@pull pull Bot added the ⤵️ pull label Jun 10, 2026
@pull pull Bot merged commit 0d49faf into code:canary Jun 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants