Skip to content

Commit

Permalink
decide wether to use APP_PAGE or PAGE kind based on actual next version
Browse files Browse the repository at this point in the history
  • Loading branch information
pieh committed Jun 14, 2024
1 parent 01168ef commit bb734c0
Showing 1 changed file with 43 additions and 25 deletions.
68 changes: 43 additions & 25 deletions src/build/content/prerendered.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { trace } from '@opentelemetry/api'
import { wrapTracer } from '@opentelemetry/api/experimental'
import { glob } from 'fast-glob'
import pLimit from 'p-limit'
import { satisfies } from 'semver'

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

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

// TODO: check actual next version and not rely on env var set by tests
const useOldStuff = process.env.NEXT_VERSION !== 'canary'
if (useOldStuff) {
const rsc = await readFile(`${path}.rsc`, 'utf-8').catch(() =>
readFile(`${path}.prefetch.rsc`, 'utf-8'),
)

// Next < v14.2.0 does not set meta.status when notFound() is called directly on a page
// Exclude Parallel routes, they are 404s when visited directly
if (
!meta.status &&
rsc.includes('NEXT_NOT_FOUND') &&
!meta.headers['x-next-cache-tags'].includes('/@')
) {
meta.status = 404
}
// supporting both old and new cache kind for App Router pages - https://github.com/vercel/next.js/pull/65988
if (shouldUseAppPageKind) {
return {
kind: 'PAGE',
kind: 'APP_PAGE',
html,
pageData: rsc,
rscData: await readFile(`${path}.rsc`, 'base64').catch(() =>
readFile(`${path}.prefetch.rsc`, 'base64'),
),
...meta,
}
}

// use new stuff
const rsc = await readFile(`${path}.rsc`, 'utf-8').catch(() =>
readFile(`${path}.prefetch.rsc`, 'utf-8'),
)

// Next < v14.2.0 does not set meta.status when notFound() is called directly on a page
// Exclude Parallel routes, they are 404s when visited directly
if (
!meta.status &&
rsc.includes('NEXT_NOT_FOUND') &&
!meta.headers['x-next-cache-tags'].includes('/@')
) {
meta.status = 404
}
return {
kind: 'APP_PAGE',
kind: 'PAGE',
html,
rscData: await readFile(`${path}.rsc`, 'base64').catch(() =>
readFile(`${path}.prefetch.rsc`, 'base64'),
),
pageData: rsc,
...meta,
}
}
Expand Down Expand Up @@ -120,6 +120,18 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>

const limitConcurrentPrerenderContentHandling = pLimit(10)

// https://github.com/vercel/next.js/pull/65988 introduced Cache kind specific to pages in App Router (`APP_PAGE`).
// Before this change there was common kind for both Pages router and App router pages
// so we check Next.js version to decide how to generate cache values for App Router pages.
// Note: at time of writing this code, released 15@rc uses old kind for App Router pages, while [email protected] and newer canaries use new kind.
// Looking at 15@rc release branch it was merging `canary` branch in, so the version constraint assumes that future 15@rc (and 15@latest) versions
// will use new kind for App Router pages.
const shouldUseAppPageKind = ctx.nextVersion
? satisfies(ctx.nextVersion, '>=15.0.0-canary.13 <15.0.0-d || >15.0.0-rc.0', {
includePrerelease: true,
})
: false

await Promise.all(
Object.entries(manifest.routes).map(
([route, meta]): Promise<void> =>
Expand All @@ -142,7 +154,10 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
value = await buildPagesCacheValue(join(ctx.publishDir, 'server/pages', key))
break
case meta.dataRoute?.endsWith('.rsc'):
value = await buildAppCacheValue(join(ctx.publishDir, 'server/app', key))
value = await buildAppCacheValue(
join(ctx.publishDir, 'server/app', key),
shouldUseAppPageKind,
)
break
case meta.dataRoute === null:
value = await buildRouteCacheValue(
Expand All @@ -164,7 +179,10 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
if (existsSync(join(ctx.publishDir, `server/app/_not-found.html`))) {
const lastModified = Date.now()
const key = '/404'
const value = await buildAppCacheValue(join(ctx.publishDir, 'server/app/_not-found'))
const value = await buildAppCacheValue(
join(ctx.publishDir, 'server/app/_not-found'),
shouldUseAppPageKind,
)
await writeCacheEntry(key, value, lastModified, ctx)
}
} catch (error) {
Expand Down

0 comments on commit bb734c0

Please sign in to comment.