From 192d8dec8f0b8c91c23c5c5b57761132a8f40e02 Mon Sep 17 00:00:00 2001 From: Hendrik Liebau Date: Fri, 28 Feb 2025 15:38:38 +0100 Subject: [PATCH] Define `expire` as `number | undefined` in `CacheControl` --- packages/next/src/export/routes/app-page.ts | 4 +-- packages/next/src/export/routes/app-route.ts | 6 ++--- packages/next/src/export/routes/pages.ts | 5 +++- .../next/src/server/app-render/app-render.tsx | 2 +- packages/next/src/server/base-server.ts | 25 +++++++++++-------- packages/next/src/server/image-optimizer.ts | 2 +- packages/next/src/server/lib/cache-control.ts | 2 +- packages/next/src/server/next-server.ts | 2 +- packages/next/src/server/render.tsx | 6 ++--- 9 files changed, 31 insertions(+), 23 deletions(-) diff --git a/packages/next/src/export/routes/app-page.ts b/packages/next/src/export/routes/app-page.ts index 75712d57431eb..4bd0b3527a626 100644 --- a/packages/next/src/export/routes/app-page.ts +++ b/packages/next/src/export/routes/app-page.ts @@ -139,7 +139,7 @@ export async function exportAppPage( const { metadata } = result const { flightData, - cacheControl = { revalidate: false }, + cacheControl = { revalidate: false, expire: undefined }, postponed, fetchTags, fetchMetrics, @@ -298,7 +298,7 @@ export async function exportAppPage( }) } - return { cacheControl: { revalidate: 0 }, fetchMetrics } + return { cacheControl: { revalidate: 0, expire: undefined }, fetchMetrics } } } diff --git a/packages/next/src/export/routes/app-route.ts b/packages/next/src/export/routes/app-route.ts index f6fcb05353354..b204e7b79ed62 100644 --- a/packages/next/src/export/routes/app-route.ts +++ b/packages/next/src/export/routes/app-route.ts @@ -114,14 +114,14 @@ export async function exportAppRoute( // unless specifically opted into experimental.dynamicIO !== true ) { - return { cacheControl: { revalidate: 0 } } + return { cacheControl: { revalidate: 0, expire: undefined } } } const response = await module.handle(request, context) const isValidStatus = response.status < 400 || response.status === 404 if (!isValidStatus) { - return { cacheControl: { revalidate: 0 } } + return { cacheControl: { revalidate: 0, expire: undefined } } } const blob = await response.blob() @@ -173,6 +173,6 @@ export async function exportAppRoute( throw err } - return { cacheControl: { revalidate: 0 } } + return { cacheControl: { revalidate: 0, expire: undefined } } } } diff --git a/packages/next/src/export/routes/pages.ts b/packages/next/src/export/routes/pages.ts index 824c4dac70298..a0f761e015bc5 100644 --- a/packages/next/src/export/routes/pages.ts +++ b/packages/next/src/export/routes/pages.ts @@ -219,7 +219,10 @@ export async function exportPagesPage( return { ampValidations, - cacheControl: metadata.cacheControl ?? { revalidate: false }, + cacheControl: metadata.cacheControl ?? { + revalidate: false, + expire: undefined, + }, ssgNotFound, } } diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index 818c5a61de122..9881709dc6a10 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -1422,7 +1422,7 @@ async function renderToHTMLOrFlightImpl( // If force static is specifically set to false, we should not revalidate // the page. if (workStore.forceStatic === false || response.collectedRevalidate === 0) { - metadata.cacheControl = { revalidate: 0 } + metadata.cacheControl = { revalidate: 0, expire: undefined } } else { // Copy the cache control value onto the render result metadata. metadata.cacheControl = { diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 954c8e6b01cbf..c87ecf85ca254 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -3116,7 +3116,7 @@ export default abstract class Server< typeof postponed !== 'undefined' ) { return { - cacheControl: { revalidate: 1 }, + cacheControl: { revalidate: 1, expire: undefined }, isFallback: false, value: { kind: CachedRouteKind.PAGES, @@ -3309,7 +3309,7 @@ export default abstract class Server< // If this is a resume request in minimal mode it is streamed with dynamic // content and should not be cached. if (minimalPostponed) { - cacheControl = { revalidate: 0 } + cacheControl = { revalidate: 0, expire: undefined } } // If this is in minimal mode and this is a flight request that isn't a @@ -3321,18 +3321,18 @@ export default abstract class Server< !isPrefetchRSCRequest && isRoutePPREnabled ) { - cacheControl = { revalidate: 0 } + cacheControl = { revalidate: 0, expire: undefined } } else if (!this.renderOpts.dev || (hasServerProps && !isNextDataRequest)) { // If this is a preview mode request, we shouldn't cache it if (isPreviewMode) { - cacheControl = { revalidate: 0 } + cacheControl = { revalidate: 0, expire: undefined } } // If this isn't SSG, then we should set change the header only if it is // not set already. else if (!isSSG) { if (!res.getHeader('Cache-Control')) { - cacheControl = { revalidate: 0 } + cacheControl = { revalidate: 0, expire: undefined } } } @@ -3348,9 +3348,10 @@ export default abstract class Server< cacheControl = { revalidate: typeof notFoundRevalidate === 'undefined' ? 0 : notFoundRevalidate, + expire: undefined, } } else if (is500Page) { - cacheControl = { revalidate: 0 } + cacheControl = { revalidate: 0, expire: undefined } } else if (cacheEntry.cacheControl) { // If the cache entry has a cache control with a revalidate value that's // a number, use it. @@ -3370,7 +3371,7 @@ export default abstract class Server< // Otherwise if the revalidate value is false, then we should use the // cache time of one year. else { - cacheControl = { revalidate: CACHE_ONE_YEAR } + cacheControl = { revalidate: CACHE_ONE_YEAR, expire: undefined } } } } @@ -3561,7 +3562,7 @@ export default abstract class Server< // postponed state. // TODO: distinguish `force-static` from pages with no postponed state (static) cacheControl: isDynamicRSCRequest - ? { revalidate: 0 } + ? { revalidate: 0, expire: undefined } : cacheEntry.cacheControl, } } @@ -3605,7 +3606,11 @@ export default abstract class Server< }) ) - return { type: 'html', body, cacheControl: { revalidate: 0 } } + return { + type: 'html', + body, + cacheControl: { revalidate: 0, expire: undefined }, + } } // This request has postponed, so let's create a new transformer that the @@ -3652,7 +3657,7 @@ export default abstract class Server< // We don't want to cache the response if it has postponed data because // the response being sent to the client it's dynamic parts are streamed // to the client on the same request. - cacheControl: { revalidate: 0 }, + cacheControl: { revalidate: 0, expire: undefined }, } } else if (isNextDataRequest) { return { diff --git a/packages/next/src/server/image-optimizer.ts b/packages/next/src/server/image-optimizer.ts index c36eaf15443a0..7346301b47b37 100644 --- a/packages/next/src/server/image-optimizer.ts +++ b/packages/next/src/server/image-optimizer.ts @@ -416,7 +416,7 @@ export class ImageOptimizerCache { revalidateAfter: Math.max(maxAge, this.nextConfig.images.minimumCacheTTL) * 1000 + Date.now(), - cacheControl: { revalidate: maxAge }, + cacheControl: { revalidate: maxAge, expire: undefined }, isStale: now > expireAt, isFallback: false, } diff --git a/packages/next/src/server/lib/cache-control.ts b/packages/next/src/server/lib/cache-control.ts index c8736eb88d331..93a8b08736909 100644 --- a/packages/next/src/server/lib/cache-control.ts +++ b/packages/next/src/server/lib/cache-control.ts @@ -11,7 +11,7 @@ export type Revalidate = number | false export interface CacheControl { revalidate: Revalidate - expire?: number + expire: number | undefined } export function getCacheControlHeader({ diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index 4ecd1770947fc..6a3bcad54a808 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -957,7 +957,7 @@ export default class NextNodeServer extends BaseServer< upstreamEtag, }, isFallback: false, - cacheControl: { revalidate: maxAge }, + cacheControl: { revalidate: maxAge, expire: undefined }, } }, { diff --git a/packages/next/src/server/render.tsx b/packages/next/src/server/render.tsx index f6ce83d5b06f4..bf642a7216d10 100644 --- a/packages/next/src/server/render.tsx +++ b/packages/next/src/server/render.tsx @@ -1049,8 +1049,8 @@ export async function renderToHTMLImpl( 'props' in data ? data.props : undefined ) - // pass up revalidate and props for export - metadata.cacheControl = { revalidate } + // pass up cache control and props for export + metadata.cacheControl = { revalidate, expire: undefined } metadata.pageData = props // this must come after revalidate is added to renderResultMeta @@ -1123,7 +1123,7 @@ export async function renderToHTMLImpl( }) ) canAccessRes = false - metadata.cacheControl = { revalidate: 0 } + metadata.cacheControl = { revalidate: 0, expire: undefined } } catch (serverSidePropsError: any) { // remove not found error code to prevent triggering legacy // 404 rendering