mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
When Cache Components is enabled, the development server threads a `fallbackParams` request meta for dynamic app routes so the staged render knows which params are not statically known and must be deferred to a later stage. The previous computation walked the prerendered routes from `getStaticPaths` and kept the one with the fewest fallback params, without checking that the route actually matched the requested URL. Consider `/mixed/[lang]/[id]` where `generateStaticParams` covers `lang: 'en'` but not `id`: the prerendered routes are the base `/mixed/[lang]/[id]`, which defers `[lang, id]`, and the covered `/mixed/en/[id]`, which defers only `[id]`. For the request `/mixed/fr/123` the fewest-fallback route is `/mixed/en/[id]`, but `en` does not match `fr`, so applying its `[id]` set left `lang` out of the fallback set and `fr` was treated as a statically known value. Because this meta decides which stage each param resolves in, and the stage decides the environment a replayed `console.log` is attributed to, treating `fr` as static resolved it in the prerender stage instead of deferring it to the runtime stage. The computation now matches the requested URL against each prerendered route with the canonical `getRouteRegex` and, among the routes that match, picks the most-specific one, the one with the fewest fallback params. For `/mixed/fr/123` only the base route matches, so its `[lang, id]` set is used and both params defer, while for `/mixed/en/123` the covered `/mixed/en/[id]` still matches and wins, so `lang` resolves statically and only `id` defers. This mirrors what a production build writes to the prerender manifest, where the server matches the URL to the most-specific prerendered route at request time. The change is development-only, gated on the route module being in dev mode, and production continues to read the manifest. A later change in this stack reads the same `fallbackParams` meta for the Instant Navigation testing API's on-demand shell render, so that path defers the identical per-URL set a production prefetch would.
44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import {
|
|
CachedInnerTraceManualSpan,
|
|
InnerTraceManualSpan,
|
|
CachedTracedComponentManualSpan,
|
|
TracedComponentManualSpan,
|
|
CachedInnerTraceActiveSpan,
|
|
InnerTraceActiveSpan,
|
|
CachedTracedComponentActiveSpan,
|
|
TracedComponentActiveSpan,
|
|
} from '../../traced-work'
|
|
|
|
// A navigation to an uncovered slug reads a deferred `params`, which is a
|
|
// blocking navigation. This suite exercises span creation during cache
|
|
// component validation, not Instant Navigation, so opt the route out of that
|
|
// validation: otherwise its blocking-route insight masks the `startActiveSpan`
|
|
// console error these tests assert.
|
|
export const instant = false
|
|
|
|
export function generateStaticParams() {
|
|
return [{ slug: 'prerendered' }]
|
|
}
|
|
|
|
export default async function Page({
|
|
params,
|
|
}: {
|
|
params: Promise<{ slug: string }>
|
|
}) {
|
|
'use cache'
|
|
return (
|
|
<>
|
|
<h1>{(await params).slug}</h1>
|
|
<div>We are inside a "use cache" scope</div>
|
|
<CachedInnerTraceManualSpan />
|
|
<InnerTraceManualSpan />
|
|
<CachedTracedComponentManualSpan />
|
|
<TracedComponentManualSpan />
|
|
<CachedInnerTraceActiveSpan />
|
|
<InnerTraceActiveSpan />
|
|
<CachedTracedComponentActiveSpan />
|
|
<TracedComponentActiveSpan />
|
|
</>
|
|
)
|
|
}
|