mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
Follow-up to #95151, implementing support for validating awaits of static params (i.e. when using `generateStaticParams`) An app shell cannot contain any link data. This poses a challenge when we're trying to re-use the dev render for instant validation, because we have to make a choice: 1. either we resolve static params (from `generateStaticParams`) in the `Static` stage, and get an accurate *static HTML shell* (used for the initial navigation), but an incorrect app shell 2. or we resolve them in the `ShellRuntime` stage and we get an accurate App Shell, but cannot validate a static HTML shell (which would contain static params) We'll use order 2 in the main render whenever client-navigating to a page with `partialPrefetching` enabled. We still need a render with order 1 for Static Shell Validation, so we perform a second, partial render that aborts before the dynamic stage (because only instant navigation needs the dynamic stage). As an optimization, we can skip the secondary render if the page doesn't have static params, because in that case the two orders are equivalent. If we're performing an initial load, we'll use order 1 (to reflect the HTML shell). in this case, we'll do a full secondary render with order 2. Same as above, we can skip the secondary render if there's no static params. --- Where params resolve (order 1 vs order 2) is controlled by `requestStore.needsSessionShell`. We then end up with two sets of "validation inputs" (mainly rendered chunks) that we can feed into static and instant validation respectively. Also note that this PR doesn't touch `environmentName`, because that required changing too many tests. This will be addressed in a follow-up.
34 lines
1.0 KiB
TypeScript
34 lines
1.0 KiB
TypeScript
import { Suspense } from 'react'
|
|
import { setTimeout } from 'timers/promises'
|
|
|
|
async function getCachedValue(slug: string) {
|
|
'use cache'
|
|
|
|
// A slow generation, so a warm reload that serves the cached entry is
|
|
// observably faster than a cold load that has to generate, and so a cold read
|
|
// is still pending at a staged-render boundary (which surfaces the cold cache
|
|
// indicator). The slug keys the entry; the value itself is just a timestamp.
|
|
await setTimeout(1000)
|
|
|
|
return new Date().toISOString()
|
|
}
|
|
|
|
async function CachedValue({ slug }: { slug: string }) {
|
|
const value = await getCachedValue(slug)
|
|
|
|
return <p id="value">{value}</p>
|
|
}
|
|
|
|
export async function PageForSlug({ slug }: { slug: string }) {
|
|
// NOTE: we're not using generateStaticParams because
|
|
// those resolve after the shell in `partialPrefetching`,
|
|
// and the test needs the cache to be part of the shell
|
|
return (
|
|
<main>
|
|
<Suspense fallback={<p id="loading">Loading...</p>}>
|
|
<CachedValue slug={slug} />
|
|
</Suspense>
|
|
</main>
|
|
)
|
|
}
|