Skip to content

Commit 1eb088f

Browse files
committed
decide wether to use APP_PAGE or PAGE kind based on actual next version
1 parent 01168ef commit 1eb088f

File tree

1 file changed

+43
-25
lines changed

1 file changed

+43
-25
lines changed

src/build/content/prerendered.ts

+43-25
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { trace } from '@opentelemetry/api'
66
import { wrapTracer } from '@opentelemetry/api/experimental'
77
import { glob } from 'fast-glob'
88
import pLimit from 'p-limit'
9+
import { satisfies } from 'semver'
910

1011
import { encodeBlobKey } from '../../shared/blobkey.js'
1112
import type {
@@ -53,41 +54,40 @@ const buildPagesCacheValue = async (path: string): Promise<NetlifyCachedPageValu
5354

5455
const buildAppCacheValue = async (
5556
path: string,
57+
shouldUseAppPageKind: boolean,
5658
): Promise<NetlifyCachedAppPageValue | NetlifyCachedPageValue> => {
5759
const meta = JSON.parse(await readFile(`${path}.meta`, 'utf-8'))
5860
const html = await readFile(`${path}.html`, 'utf-8')
5961

60-
// TODO: check actual next version and not rely on env var set by tests
61-
const useOldStuff = process.env.NEXT_VERSION !== 'canary'
62-
if (useOldStuff) {
63-
const rsc = await readFile(`${path}.rsc`, 'utf-8').catch(() =>
64-
readFile(`${path}.prefetch.rsc`, 'utf-8'),
65-
)
66-
67-
// Next < v14.2.0 does not set meta.status when notFound() is called directly on a page
68-
// Exclude Parallel routes, they are 404s when visited directly
69-
if (
70-
!meta.status &&
71-
rsc.includes('NEXT_NOT_FOUND') &&
72-
!meta.headers['x-next-cache-tags'].includes('/@')
73-
) {
74-
meta.status = 404
75-
}
62+
// supporting both old and new cache kind for App Router pages - https://github.com/vercel/next.js/pull/65988
63+
if (shouldUseAppPageKind) {
7664
return {
77-
kind: 'PAGE',
65+
kind: 'APP_PAGE',
7866
html,
79-
pageData: rsc,
67+
rscData: await readFile(`${path}.rsc`, 'base64').catch(() =>
68+
readFile(`${path}.prefetch.rsc`, 'base64'),
69+
),
8070
...meta,
8171
}
8272
}
8373

84-
// use new stuff
74+
const rsc = await readFile(`${path}.rsc`, 'utf-8').catch(() =>
75+
readFile(`${path}.prefetch.rsc`, 'utf-8'),
76+
)
77+
78+
// Next < v14.2.0 does not set meta.status when notFound() is called directly on a page
79+
// Exclude Parallel routes, they are 404s when visited directly
80+
if (
81+
!meta.status &&
82+
rsc.includes('NEXT_NOT_FOUND') &&
83+
!meta.headers['x-next-cache-tags'].includes('/@')
84+
) {
85+
meta.status = 404
86+
}
8587
return {
86-
kind: 'APP_PAGE',
88+
kind: 'PAGE',
8789
html,
88-
rscData: await readFile(`${path}.rsc`, 'base64').catch(() =>
89-
readFile(`${path}.prefetch.rsc`, 'base64'),
90-
),
90+
pageData: rsc,
9191
...meta,
9292
}
9393
}
@@ -120,6 +120,18 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
120120

121121
const limitConcurrentPrerenderContentHandling = pLimit(10)
122122

123+
// https://github.com/vercel/next.js/pull/65988 introduced Cache kind specific to pages in App Router (`APP_PAGE`).
124+
// Before this change there was common kind for both Pages router and App router pages
125+
// so we check Next.js version to decide how to generate cache values for App Router pages.
126+
// Note: at time of writing this code, released 15@rc uses old kind for App Router pages, while canaries after [email protected] use new kind.
127+
// Looking at 15@rc release branch it was merging `canary` branch in, so the version constraint assume that future 15@rc (and 15@latest) versions
128+
// will use new kind for App Router pages.
129+
const shouldUseAppPageKind = ctx.nextVersion
130+
? satisfies(ctx.nextVersion, '>=15.0.0-canary.13 <15.0.0-d || >15.0.0-rc.0', {
131+
includePrerelease: true,
132+
})
133+
: false
134+
123135
await Promise.all(
124136
Object.entries(manifest.routes).map(
125137
([route, meta]): Promise<void> =>
@@ -142,7 +154,10 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
142154
value = await buildPagesCacheValue(join(ctx.publishDir, 'server/pages', key))
143155
break
144156
case meta.dataRoute?.endsWith('.rsc'):
145-
value = await buildAppCacheValue(join(ctx.publishDir, 'server/app', key))
157+
value = await buildAppCacheValue(
158+
join(ctx.publishDir, 'server/app', key),
159+
shouldUseAppPageKind,
160+
)
146161
break
147162
case meta.dataRoute === null:
148163
value = await buildRouteCacheValue(
@@ -164,7 +179,10 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
164179
if (existsSync(join(ctx.publishDir, `server/app/_not-found.html`))) {
165180
const lastModified = Date.now()
166181
const key = '/404'
167-
const value = await buildAppCacheValue(join(ctx.publishDir, 'server/app/_not-found'))
182+
const value = await buildAppCacheValue(
183+
join(ctx.publishDir, 'server/app/_not-found'),
184+
shouldUseAppPageKind,
185+
)
168186
await writeCacheEntry(key, value, lastModified, ctx)
169187
}
170188
} catch (error) {

0 commit comments

Comments
 (0)