Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pathname to PrerenderStore #70889

Merged
merged 2 commits into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ async function renderToHTMLOrFlightImpl(
])
}

addImplicitTags(workStore, requestStore, undefined)
addImplicitTags(workStore, requestStore, undefined, undefined)

if (workStore.tags) {
metadata.fetchTags = workStore.tags.join(',')
Expand Down Expand Up @@ -1237,7 +1237,7 @@ async function renderToHTMLOrFlightImpl(
])
}

addImplicitTags(workStore, requestStore, undefined)
addImplicitTags(workStore, requestStore, undefined, undefined)

if (workStore.tags) {
metadata.fetchTags = workStore.tags.join(',')
Expand Down Expand Up @@ -1852,6 +1852,7 @@ async function prerenderToStream(
const cacheSignal = new CacheSignal()
const prospectiveRenderPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
cacheSignal,
// During the prospective render we don't want to synchronously abort on dynamic access
// because it could prevent us from discovering all caches in siblings. So we omit the controller
Expand Down Expand Up @@ -1943,6 +1944,7 @@ async function prerenderToStream(

const finalRenderPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
// During the final prerender we don't need to track cache access so we omit the signal
cacheSignal: null,
// During the final render we do want to abort synchronously on dynamic access so we
Expand Down Expand Up @@ -1998,6 +2000,7 @@ async function prerenderToStream(
const SSRController = new AbortController()
const ssrPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
// For HTML Generation we don't need to track cache reads (RSC only)
cacheSignal: null,
// We expect the SSR render to complete in a single Task and need to be able to synchronously abort
Expand Down Expand Up @@ -2202,6 +2205,7 @@ async function prerenderToStream(
const cacheSignal = new CacheSignal()
const prospectiveRenderPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
cacheSignal,
// When PPR is off we can synchronously abort the prospective render because we will
// always hit this path on the final render and thus we can skip the final render and just
Expand Down Expand Up @@ -2280,6 +2284,7 @@ async function prerenderToStream(

const finalRenderPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
// During the final prerender we don't need to track cache access so we omit the signal
cacheSignal: null,
controller: flightController,
Expand All @@ -2289,6 +2294,7 @@ async function prerenderToStream(
const SSRController = new AbortController()
const ssrPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
// For HTML Generation we don't need to track cache reads (RSC only)
cacheSignal: null,
// We expect the SSR render to complete in a single Task and need to be able to synchronously abort
Expand Down Expand Up @@ -2469,6 +2475,7 @@ async function prerenderToStream(
)
const reactServerPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
cacheSignal: null,
controller: null,
dynamicTracking,
Expand Down Expand Up @@ -2496,6 +2503,7 @@ async function prerenderToStream(

const ssrPrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: ctx.requestStore.url.pathname,
cacheSignal: null,
controller: null,
dynamicTracking,
Expand Down Expand Up @@ -2653,6 +2661,7 @@ async function prerenderToStream(
} else {
const prerenderLegacyStore: PrerenderStore = {
type: 'prerender-legacy',
pathname: ctx.requestStore.url.pathname,
}
// This is a regular static generation. We don't do dynamic tracking because we rely on
// the old-school dynamic error handling to bail out of static generation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { prerenderAsyncStorage } from './prerender-async-storage-instance' with
*/
export type PrerenderStoreModern = {
type: 'prerender'
pathname: string | undefined
/**
* This is the AbortController passed to React. It can be used to abort the prerender
* if we encounter conditions that do not require further rendering
Expand All @@ -38,6 +39,7 @@ export type PrerenderStoreModern = {

export type PrerenderStoreLegacy = {
type: 'prerender-legacy'
pathname: string | undefined
}

export type PrerenderStore = PrerenderStoreLegacy | PrerenderStoreModern
Expand Down
17 changes: 13 additions & 4 deletions packages/next/src/server/lib/patch-fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
RequestAsyncStorage,
RequestStore,
} from '../../client/components/request-async-storage.external'
import type { PrerenderStore } from '../app-render/prerender-async-storage.external'
import {
cacheAsyncStorage,
type CacheStore,
Expand Down Expand Up @@ -144,6 +145,7 @@ const getDerivedTags = (pathname: string): string[] => {
export function addImplicitTags(
workStore: WorkStore,
requestStore: RequestStore | undefined,
prerenderStore: PrerenderStore | undefined,
cacheStore: CacheStore | undefined
) {
const newTags: string[] = []
Expand Down Expand Up @@ -174,10 +176,17 @@ export function addImplicitTags(
newTags.push(tag)
}

const renderedPathname =
requestStore !== undefined
? requestStore.url.pathname
: prerenderStore !== undefined
? prerenderStore.pathname
: undefined

// Add the tags from the pathname. If the route has unknown params, we don't
// want to add the pathname as a tag, as it will be invalid.
if (requestStore?.url.pathname && !hasFallbackRouteParams) {
const tag = `${NEXT_CACHE_IMPLICIT_TAG_ID}${requestStore.url.pathname}`
if (renderedPathname && !hasFallbackRouteParams) {
const tag = `${NEXT_CACHE_IMPLICIT_TAG_ID}${renderedPathname}`
if (
!cacheStore ||
(cacheStore.type !== 'cache' && cacheStore.type !== 'unstable-cache')
Expand Down Expand Up @@ -263,6 +272,7 @@ export function createPatchedFetcher(
const hideSpan = process.env.NEXT_OTEL_FETCH_DISABLED === '1'

const workStore = workAsyncStorage.getStore()
const prerenderStore = prerenderAsyncStorage.getStore()

const result = getTracer().trace(
isInternal ? NextNodeServerSpan.internalFetch : AppRenderSpan.fetch,
Expand Down Expand Up @@ -345,6 +355,7 @@ export function createPatchedFetcher(
const implicitTags = addImplicitTags(
workStore,
requestStore,
prerenderStore,
cacheStore
)

Expand Down Expand Up @@ -772,7 +783,6 @@ export function createPatchedFetcher(
// We sometimes use the cache to dedupe fetches that do not specify a cache configuration
// In these cases we want to make sure we still exclude them from prerenders if dynamicIO is on
// so we introduce an artificial Task boundary here.
const prerenderStore = prerenderAsyncStorage.getStore()
if (prerenderStore) {
await waitAtLeastOneReactRenderTask()
}
Expand Down Expand Up @@ -953,7 +963,6 @@ export function createPatchedFetcher(
}
)

const prerenderStore = prerenderAsyncStorage.getStore()
if (
prerenderStore &&
prerenderStore.type === 'prerender' &&
Expand Down
5 changes: 4 additions & 1 deletion packages/next/src/server/route-modules/app-route/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ export class AppRouteRouteModule extends RouteModule<
let dynamicTracking = createDynamicTrackingState(undefined)
const prospectiveRoutePrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: requestStore.url.pathname,
cacheSignal,
// During prospective render we don't use a controller
// because we need to let all caches fill.
Expand Down Expand Up @@ -403,6 +404,7 @@ export class AppRouteRouteModule extends RouteModule<

const finalRoutePrerenderStore: PrerenderStore = {
type: 'prerender',
pathname: requestStore.url.pathname,
cacheSignal: null,
controller,
dynamicTracking,
Expand Down Expand Up @@ -466,6 +468,7 @@ export class AppRouteRouteModule extends RouteModule<
res = await prerenderAsyncStorage.run(
{
type: 'prerender-legacy',
pathname: requestStore.url.pathname,
},
handler,
request,
Expand Down Expand Up @@ -522,7 +525,7 @@ export class AppRouteRouteModule extends RouteModule<
...Object.values(workStore.pendingRevalidates || {}),
])

addImplicitTags(workStore, requestStore, undefined)
addImplicitTags(workStore, requestStore, undefined, undefined)
;(context.renderOpts as any).fetchTags = workStore.tags?.join(',')

// It's possible cookies were set in the handler, so we need
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export function unstable_cache<T extends Callback>(
const implicitTags = addImplicitTags(
workStore,
requestStore,
prerenderStore,
cacheStore
)

Expand Down Expand Up @@ -305,7 +306,8 @@ export function unstable_cache<T extends Callback>(
// @TODO check on this API. addImplicitTags mutates the store and returns the implicit tags. The naming
// of this function is potentially a little confusing
const implicitTags =
workStore && addImplicitTags(workStore, requestStore, cacheStore)
workStore &&
addImplicitTags(workStore, requestStore, prerenderStore, cacheStore)

const cacheEntry = await incrementalCache.get(cacheKey, {
kind: IncrementalCacheKind.FETCH,
Expand Down
Loading