Skip to content

Commit f31d30c

Browse files
committed
feat: reduce 404 caching scope to just the 404 page itself
1 parent 45ce211 commit f31d30c

File tree

2 files changed

+84
-22
lines changed

2 files changed

+84
-22
lines changed

src/run/headers.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,9 @@ export const setCacheControlHeaders = (
261261
}
262262

263263
if (
264-
process.env.ENABLE_404_CACHING &&
265-
['GET', 'HEAD'].includes(request.method) &&
266-
!headers.has('cdn-cache-control') &&
267-
!headers.has('netlify-cdn-cache-control')
264+
process.env.CACHE_404_PAGE &&
265+
request.url.endsWith('/404') &&
266+
['GET', 'HEAD'].includes(request.method)
268267
) {
269268
// handle CDN Cache Control on 404 Page responses
270269
setCacheControlFromRequestContext(headers, requestContext.pageHandlerRevalidate)

tests/integration/page-router.test.ts

+81-18
Original file line numberDiff line numberDiff line change
@@ -152,15 +152,10 @@ test<FixtureTestContext>('Should serve correct locale-aware custom 404 pages', a
152152
).toBe('fr')
153153
})
154154

155-
describe('404 caching', () => {
156-
beforeAll(() => {
157-
process.env.ENABLE_404_CACHING = 'true'
158-
})
159-
160-
afterAll(() => {
161-
delete process.env.ENABLE_404_CACHING
162-
})
163-
155+
// These tests describe how the 404 caching should work, but unfortunately it doesn't work like
156+
// this in v5 and a fix would represent a breaking change so we are skipping them for now, but
157+
// leaving them here for future reference when considering the next major version
158+
describe.skip('404 caching', () => {
164159
describe('404 without getStaticProps', () => {
165160
test<FixtureTestContext>('not matching dynamic paths should be cached permanently', async (ctx) => {
166161
await createFixture('page-router', ctx)
@@ -177,7 +172,7 @@ describe('404 caching', () => {
177172
'should be cached permanently',
178173
).toBe('s-maxage=31536000, stale-while-revalidate=31536000, durable')
179174
})
180-
test<FixtureTestContext>('matching dynamic path with revalidate should be cached permanently', async (ctx) => {
175+
test<FixtureTestContext>('matching dynamic path with revalidate should be cached for revalidate time', async (ctx) => {
181176
await createFixture('page-router', ctx)
182177
await runPlugin(ctx)
183178

@@ -189,8 +184,8 @@ describe('404 caching', () => {
189184

190185
expect(
191186
notExistingPage.headers['netlify-cdn-cache-control'],
192-
'should be cached permanently',
193-
).toBe('s-maxage=31536000, stale-while-revalidate=31536000, durable')
187+
'should be cached for revalidate time',
188+
).toBe('s-maxage=600, stale-while-revalidate=31536000, durable')
194189
})
195190
})
196191

@@ -210,7 +205,7 @@ describe('404 caching', () => {
210205
'should be cached permanently',
211206
).toBe('s-maxage=31536000, stale-while-revalidate=31536000, durable')
212207
})
213-
test<FixtureTestContext>('matching dynamic path with revalidate should be cached permanently', async (ctx) => {
208+
test<FixtureTestContext>('matching dynamic path with revalidate should be cached for revalidate time', async (ctx) => {
214209
await createFixture('page-router-base-path-i18n', ctx)
215210
await runPlugin(ctx)
216211

@@ -222,8 +217,8 @@ describe('404 caching', () => {
222217

223218
expect(
224219
notExistingPage.headers['netlify-cdn-cache-control'],
225-
'should be cached permanently',
226-
).toBe('s-maxage=31536000, stale-while-revalidate=31536000, durable')
220+
'should be cached for revalidate time',
221+
).toBe('s-maxage=600, stale-while-revalidate=31536000, durable')
227222
})
228223
})
229224

@@ -251,7 +246,7 @@ describe('404 caching', () => {
251246
).toBe('s-maxage=300, stale-while-revalidate=31536000, durable')
252247
})
253248

254-
test<FixtureTestContext>('matching dynamic path with revalidate should be cached for 404 page revalidate', async (ctx) => {
249+
test<FixtureTestContext>('matching dynamic path with revalidate should be cached for revalidate time', async (ctx) => {
255250
await createFixture('page-router-404-get-static-props-with-revalidate', ctx)
256251
await runPlugin(ctx)
257252

@@ -269,8 +264,76 @@ describe('404 caching', () => {
269264

270265
expect(
271266
notExistingPage.headers['netlify-cdn-cache-control'],
272-
'should be cached for 404 page revalidate',
273-
).toBe('s-maxage=300, stale-while-revalidate=31536000, durable')
267+
'should be cached for revalidate time',
268+
).toBe('s-maxage=600, stale-while-revalidate=31536000, durable')
269+
})
270+
})
271+
})
272+
273+
// This is a temporary fix to ensure that the 404 page itself is cached correctly when requested
274+
// directly. This is a workaround for a specific customer and should be removed once the 404 caching
275+
// is fixed in the next major version.
276+
describe.only('404 page caching', () => {
277+
beforeAll(() => {
278+
process.env.CACHE_404_PAGE = 'true'
279+
})
280+
281+
afterAll(() => {
282+
delete process.env.CACHE_404_PAGE
283+
})
284+
285+
test<FixtureTestContext>('404 without getStaticProps', async (ctx) => {
286+
await createFixture('page-router', ctx)
287+
await runPlugin(ctx)
288+
289+
const notExistingPage = await invokeFunction(ctx, {
290+
url: '/404',
291+
})
292+
293+
expect(notExistingPage.statusCode).toBe(404)
294+
295+
expect(
296+
notExistingPage.headers['netlify-cdn-cache-control'],
297+
'should be cached permanently',
298+
).toBe('s-maxage=31536000, stale-while-revalidate=31536000, durable')
299+
})
300+
301+
test<FixtureTestContext>('404 with getStaticProps without revalidate', async (ctx) => {
302+
await createFixture('page-router-base-path-i18n', ctx)
303+
await runPlugin(ctx)
304+
305+
const notExistingPage = await invokeFunction(ctx, {
306+
url: '/base/404',
307+
})
308+
309+
expect(notExistingPage.statusCode).toBe(404)
310+
311+
expect(
312+
notExistingPage.headers['netlify-cdn-cache-control'],
313+
'should be cached permanently',
314+
).toBe('s-maxage=31536000, stale-while-revalidate=31536000, durable')
315+
})
316+
317+
test<FixtureTestContext>('404 with getStaticProps with revalidate', async (ctx) => {
318+
await createFixture('page-router-404-get-static-props-with-revalidate', ctx)
319+
await runPlugin(ctx)
320+
321+
// ignoring initial stale case
322+
await invokeFunction(ctx, {
323+
url: '/404',
274324
})
325+
326+
await new Promise((res) => setTimeout(res, 100))
327+
328+
const notExistingPage = await invokeFunction(ctx, {
329+
url: '/404',
330+
})
331+
332+
expect(notExistingPage.statusCode).toBe(404)
333+
334+
expect(
335+
notExistingPage.headers['netlify-cdn-cache-control'],
336+
'should be cached for 404 page revalidate',
337+
).toBe('s-maxage=300, stale-while-revalidate=31536000, durable')
275338
})
276339
})

0 commit comments

Comments
 (0)