next.js
fd712f38 - Cached Navigations: Cache runtime stage data from navigation requests

Commit
6 days ago
Cached Navigations: Cache runtime stage data from navigation requests When navigating to a page with `unstable_instant: { prefetch: 'runtime' }` and no prior prefetch (e.g. `prefetch={false}` or clicking before prefetch completes), the server now embeds a runtime prefetch stream in the dynamic RSC navigation payload. On the client, this stream is decoded and written into the segment cache so that subsequent navigations to the same page can serve runtime-prefetchable content (cookies, headers, searchParams) instantly, without needing a separate prefetch request. On the server, `generateStagedDynamicFlightRenderResult` detects routes with runtime prefetching enabled and attaches a `CacheSignal` and `PrerenderResumeDataCache` to the `RequestStore`. The dynamic render fills these caches as a side effect. Once `cacheSignal.cacheReady()` resolves, a final runtime prerender (the same 5-stage pipeline used for regular runtime prefetches) runs and its output is piped into a `TransformStream` whose readable side is included in the RSC payload as the `p` field on the `NavigationFlightResponse`. This avoids a separate prospective prerender because the dynamic render has already warmed the caches. On the client, `processRuntimePrefetchStream` strips the completeness marker, decodes the inner Flight stream, and the result is written into the segment cache via `writeDynamicRenderResponseIntoCache` with `FetchStrategy.PPRRuntime`. Both the `navigateToUnknownRoute` and `fetchMissingDynamicData` code paths handle the new stream. This is gated on the explicit `unstable_instant` opt-in because it adds extra server processing (a full runtime prerender per navigation request) and increases payload size. It also requires that the runtime prefetch output has been validated first. Known limitation: the runtime prefetch cache write currently evicts the static cache entry (which may have a longer stale time) because `upsertSegmentEntry` treats the fallback match as a replacement target. This means that after the runtime cache expires, the static cache is no longer available as a fallback. A follow-up will address this with a layered cache approach where entries with different fetch strategies and stale times coexist independently. Extracting runtime data from initial HTML loads (the PPR resume path) is also deferred to a follow-up.
Author
Parents
Loading