Skip to content

Commit 992a1e3

Browse files
committed
fix: don't permamently cache fallback html
1 parent 5b3234e commit 992a1e3

File tree

5 files changed

+44
-7
lines changed

5 files changed

+44
-7
lines changed

src/build/content/prerendered.ts

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { glob } from 'fast-glob'
99
import pLimit from 'p-limit'
1010
import { satisfies } from 'semver'
1111

12+
import { FS_BLOBS_MANIFEST } from '../../run/constants.js'
13+
import { type FSBlobsManifest } from '../../run/next.cjs'
1214
import { encodeBlobKey } from '../../shared/blobkey.js'
1315
import type {
1416
CachedFetchValueForMultipleVersions,
@@ -158,6 +160,11 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
158160
})
159161
: false
160162

163+
const fsBlobsManifest = {
164+
fallbackPaths: [],
165+
outputRoot: posixJoin(ctx.relativeAppDir, ctx.distDir),
166+
} satisfies FSBlobsManifest
167+
161168
await Promise.all([
162169
...Object.entries(manifest.routes).map(
163170
([route, meta]): Promise<void> =>
@@ -254,6 +261,10 @@ export const copyPrerenderedContent = async (ctx: PluginContext): Promise<void>
254261
)
255262
await writeCacheEntry(key, value, lastModified, ctx)
256263
}
264+
await writeFile(
265+
join(ctx.serverHandlerDir, FS_BLOBS_MANIFEST),
266+
JSON.stringify(fsBlobsManifest),
267+
)
257268
} catch (error) {
258269
ctx.failBuild('Failed assembling prerendered content for upload', error)
259270
}

src/run/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export const MODULE_DIR = fileURLToPath(new URL('.', import.meta.url))
55
export const PLUGIN_DIR = resolve(`${MODULE_DIR}../../..`)
66
// a file where we store the required-server-files config object in to access during runtime
77
export const RUN_CONFIG = 'run-config.json'
8+
export const FS_BLOBS_MANIFEST = 'fs-blobs-manifest.json'

src/run/handlers/request-context.cts

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export type RequestContext = {
1111
responseCacheGetLastModified?: number
1212
responseCacheKey?: string
1313
responseCacheTags?: string[]
14-
usedFsRead?: boolean
14+
usedFsReadForNonFallback?: boolean
1515
didPagesRouterOnDemandRevalidate?: boolean
1616
serverTiming?: string
1717
routeHandlerRevalidate?: NetlifyCachedRouteValue['revalidate']

src/run/headers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export const setCacheControlHeaders = (
263263
cacheControl === null &&
264264
!headers.has('cdn-cache-control') &&
265265
!headers.has('netlify-cdn-cache-control') &&
266-
requestContext.usedFsRead
266+
requestContext.usedFsReadForNonFallback
267267
) {
268268
// handle CDN Cache Control on static files
269269
headers.set('cache-control', 'public, max-age=0, must-revalidate')

src/run/next.cts

+30-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import fs from 'fs/promises'
1+
import fs, { readFile } from 'fs/promises'
22
import { relative, resolve } from 'path'
33

44
// @ts-expect-error no types installed
@@ -80,6 +80,27 @@ console.timeEnd('import next server')
8080

8181
type FS = typeof import('fs')
8282

83+
export type FSBlobsManifest = {
84+
fallbackPaths: string[]
85+
outputRoot: string
86+
}
87+
88+
function normalizeStaticAssetPath(path: string) {
89+
return path.startsWith('/') ? path : `/${path}`
90+
}
91+
92+
let fsBlobsManifestPromise: Promise<FSBlobsManifest> | undefined
93+
const getFSBlobsManifest = (): Promise<FSBlobsManifest> => {
94+
if (!fsBlobsManifestPromise) {
95+
fsBlobsManifestPromise = (async () => {
96+
const { FS_BLOBS_MANIFEST, PLUGIN_DIR } = await import('./constants.js')
97+
return JSON.parse(await readFile(resolve(PLUGIN_DIR, FS_BLOBS_MANIFEST), 'utf-8'))
98+
})()
99+
}
100+
101+
return fsBlobsManifestPromise
102+
}
103+
83104
export async function getMockedRequestHandlers(...args: Parameters<typeof getRequestHandlers>) {
84105
const tracer = getTracer()
85106
return tracer.withActiveSpan('mocked request handler', async () => {
@@ -96,13 +117,17 @@ export async function getMockedRequestHandlers(...args: Parameters<typeof getReq
96117
} catch (error) {
97118
// only try to get .html files from the blob store
98119
if (typeof path === 'string' && path.endsWith('.html')) {
120+
const fsBlobsManifest = await getFSBlobsManifest()
121+
99122
const store = getRegionalBlobStore()
100-
const relPath = relative(resolve('.next/server/pages'), path)
123+
const relPath = relative(resolve(fsBlobsManifest.outputRoot, '/server/pages'), path)
101124
const file = await store.get(await encodeBlobKey(relPath))
102125
if (file !== null) {
103-
const requestContext = getRequestContext()
104-
if (requestContext) {
105-
requestContext.usedFsRead = true
126+
if (!fsBlobsManifest.fallbackPaths.includes(normalizeStaticAssetPath(relPath))) {
127+
const requestContext = getRequestContext()
128+
if (requestContext) {
129+
requestContext.usedFsReadForNonFallback = true
130+
}
106131
}
107132

108133
return file

0 commit comments

Comments
 (0)