Skip to content

Commit b2614f2

Browse files
committed
label as Prefetch/Prefetchable depending on prefetch config
1 parent 0601503 commit b2614f2

File tree

3 files changed

+61
-13
lines changed

3 files changed

+61
-13
lines changed

packages/next/src/server/app-render/app-render.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ import { createPromiseWithResolvers } from '../../shared/lib/promise-with-resolv
212212
import { ImageConfigContext } from '../../shared/lib/image-config-context.shared-runtime'
213213
import { imageConfigDefault } from '../../shared/lib/image-config'
214214
import { RenderStage, StagedRenderingController } from './staged-rendering'
215+
import { anySegmentHasRuntimePrefetchEnabled } from './staged-validation'
215216

216217
export type GetDynamicParamFromSegment = (
217218
// [slug] / [[slug]] / [...slug]
@@ -2768,7 +2769,16 @@ async function renderWithRestartOnCacheMissInDev(
27682769
getPayload: (requestStore: RequestStore) => Promise<RSCPayload>,
27692770
onError: (error: unknown) => void
27702771
) {
2771-
const { htmlRequestId, renderOpts, requestId } = ctx
2772+
const {
2773+
htmlRequestId,
2774+
renderOpts,
2775+
requestId,
2776+
componentMod: {
2777+
routeModule: {
2778+
userland: { loaderTree },
2779+
},
2780+
},
2781+
} = ctx
27722782
const {
27732783
clientReferenceManifest,
27742784
ComponentMod,
@@ -2777,6 +2787,9 @@ async function renderWithRestartOnCacheMissInDev(
27772787
} = renderOpts
27782788
assertClientReferenceManifest(clientReferenceManifest)
27792789

2790+
const hasRuntimePrefetch =
2791+
await anySegmentHasRuntimePrefetchEnabled(loaderTree)
2792+
27802793
// If the render is restarted, we'll recreate a fresh request store
27812794
let requestStore: RequestStore = initialRequestStore
27822795

@@ -2786,8 +2799,7 @@ async function renderWithRestartOnCacheMissInDev(
27862799
case RenderStage.Static:
27872800
return 'Prerender'
27882801
case RenderStage.Runtime:
2789-
// TODO: only label as "Prefetch" if the page has a `prefetch` config.
2790-
return 'Prefetch'
2802+
return hasRuntimePrefetch ? 'Prefetch' : 'Prefetchable'
27912803
case RenderStage.Dynamic:
27922804
return 'Server'
27932805
default:
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { getLayoutOrPageModule } from '../lib/app-dir-module'
2+
import type { LoaderTree } from '../lib/app-dir-module'
3+
import { parseLoaderTree } from '../../shared/lib/router/utils/parse-loader-tree'
4+
import type { AppSegmentConfig } from '../../build/segment-config/app/app-segment-config'
5+
6+
export async function anySegmentHasRuntimePrefetchEnabled(
7+
tree: LoaderTree
8+
): Promise<boolean> {
9+
const { mod: layoutOrPageMod } = await getLayoutOrPageModule(tree)
10+
11+
// TODO(restart-on-cache-miss): Does this work correctly for client page/layout modules?
12+
const prefetchConfig = layoutOrPageMod
13+
? (layoutOrPageMod as AppSegmentConfig).unstable_prefetch
14+
: undefined
15+
/** Whether this segment should use a runtime prefetch instead of a static prefetch. */
16+
const hasRuntimePrefetch = prefetchConfig?.mode === 'runtime'
17+
if (hasRuntimePrefetch) {
18+
return true
19+
}
20+
21+
const { parallelRoutes } = parseLoaderTree(tree)
22+
for (const parallelRouteKey in parallelRoutes) {
23+
const parallelRoute = parallelRoutes[parallelRouteKey]
24+
const hasChildRuntimePrefetch =
25+
await anySegmentHasRuntimePrefetchEnabled(parallelRoute)
26+
if (hasChildRuntimePrefetch) {
27+
return true
28+
}
29+
}
30+
31+
return false
32+
}

test/development/app-dir/cache-components-dev-warmup/cache-components.dev-warmup.test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('cache-components-dev-warmup', () => {
2929
) {
3030
// Match logs that contain the message, with any environment.
3131
const logPattern = new RegExp(
32-
`^(?=.*\\b${message}\\b)(?=.*\\b(Cache|Prerender|Prefetch|Server)\\b).*`
32+
`^(?=.*\\b${message}\\b)(?=.*\\b(Cache|Prerender|Prefetch|Prefetchable|Server)\\b).*`
3333
)
3434
const logMessages = logs.map((log) => log.message)
3535
const messages = logMessages.filter((message) => logPattern.test(message))
@@ -175,12 +175,12 @@ describe('cache-components-dev-warmup', () => {
175175

176176
// Private caches are dynamic holes in static prerenders,
177177
// so they shouldn't resolve in the static stage.
178-
assertLog(logs, 'after private cache read - page', 'Prefetch')
179-
assertLog(logs, 'after private cache read - layout', 'Prefetch')
178+
assertLog(logs, 'after private cache read - page', 'Prefetchable')
179+
assertLog(logs, 'after private cache read - layout', 'Prefetchable')
180180
assertLog(
181181
logs,
182182
'after successive private cache reads - page',
183-
'Prefetch'
183+
'Prefetchable'
184184
)
185185

186186
assertLog(logs, 'after uncached fetch - layout', 'Server')
@@ -204,8 +204,12 @@ describe('cache-components-dev-warmup', () => {
204204

205205
// Short lived caches are dynamic holes in static prerenders,
206206
// so they shouldn't resolve in the static stage.
207-
assertLog(logs, 'after short-lived cache read - page', 'Prefetch')
208-
assertLog(logs, 'after short-lived cache read - layout', 'Prefetch')
207+
assertLog(logs, 'after short-lived cache read - page', 'Prefetchable')
208+
assertLog(
209+
logs,
210+
'after short-lived cache read - layout',
211+
'Prefetchable'
212+
)
209213

210214
assertLog(logs, 'after uncached fetch - layout', 'Server')
211215
assertLog(logs, 'after uncached fetch - page', 'Server')
@@ -247,10 +251,10 @@ describe('cache-components-dev-warmup', () => {
247251
assertLog(logs, 'after cache read - page', 'Prerender')
248252

249253
// TODO: we should only label this as "Prefetch" if there's a prefetch config.
250-
assertLog(logs, `after cookies`, 'Prefetch')
251-
assertLog(logs, `after headers`, 'Prefetch')
252-
assertLog(logs, `after params`, 'Prefetch')
253-
assertLog(logs, `after searchParams`, 'Prefetch')
254+
assertLog(logs, `after cookies`, 'Prefetchable')
255+
assertLog(logs, `after headers`, 'Prefetchable')
256+
assertLog(logs, `after params`, 'Prefetchable')
257+
assertLog(logs, `after searchParams`, 'Prefetchable')
254258

255259
assertLog(logs, 'after connection', 'Server')
256260
}

0 commit comments

Comments
 (0)