Skip to content

Commit 848c558

Browse files
committed
Add fallbackExpire to prerender manifest
1 parent 95111db commit 848c558

File tree

3 files changed

+36
-23
lines changed

3 files changed

+36
-23
lines changed

packages/next/src/build/index.ts

+14-6
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ export interface DynamicPrerenderManifestRoute {
279279
*/
280280
fallbackRevalidate: Revalidate | undefined
281281

282+
/**
283+
* When defined, it describes the expire configuration for the fallback route.
284+
*/
285+
fallbackExpire: Revalidate | undefined
286+
282287
/**
283288
* The headers that should used when serving the fallback.
284289
*/
@@ -3037,12 +3042,13 @@ export default async function build(
30373042
const fallbackMode =
30383043
route.fallbackMode ?? FallbackMode.NOT_FOUND
30393044

3040-
// When we're configured to serve a prerender, we should use the
3041-
// fallback revalidate from the export result. If it can't be
3042-
// found, mark that we should keep the shell forever (`false`).
3043-
let fallbackRevalidate: Revalidate | undefined =
3045+
// When the route is configured to serve a prerender, we should
3046+
// use the cache control from the export result. If it can't be
3047+
// found, mark that we should keep the shell forever
3048+
// (revalidate: `false` via `getCacheControl()`).
3049+
const fallbackCacheControl =
30443050
isRoutePPREnabled && fallbackMode === FallbackMode.PRERENDER
3045-
? cacheControl.revalidate
3051+
? cacheControl
30463052
: undefined
30473053

30483054
const fallback: Fallback = fallbackModeToFallbackField(
@@ -3072,7 +3078,8 @@ export default async function build(
30723078
),
30733079
dataRoute,
30743080
fallback,
3075-
fallbackRevalidate,
3081+
fallbackRevalidate: fallbackCacheControl?.revalidate,
3082+
fallbackExpire: fallbackCacheControl?.expire,
30763083
fallbackStatus: meta.status,
30773084
fallbackHeaders: meta.headers,
30783085
fallbackRootParams: route.fallbackRootParams,
@@ -3521,6 +3528,7 @@ export default async function build(
35213528
? `${normalizedRoute}.html`
35223529
: false,
35233530
fallbackRevalidate: undefined,
3531+
fallbackExpire: undefined,
35243532
fallbackSourceRoute: undefined,
35253533
fallbackRootParams: undefined,
35263534
dataRouteRegex: normalizeRouteRegex(

test/e2e/app-dir/use-cache/app/[id]/page.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import { unstable_cacheLife } from 'next/cache'
2+
13
async function getCachedRandom(n: number) {
24
'use cache'
5+
unstable_cacheLife('weeks')
36
return String(Math.ceil(Math.random() * n))
47
}
58

@@ -11,5 +14,7 @@ export async function generateStaticParams() {
1114
}
1215

1316
export default async function Page() {
14-
return 'hit'
17+
const value = getCachedRandom(1)
18+
19+
return <p>{value}</p>
1520
}

test/e2e/app-dir/use-cache/use-cache.test.ts

+16-16
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
createRenderResumeDataCache,
88
RenderResumeDataCache,
99
} from 'next/dist/server/resume-data-cache/resume-data-cache'
10+
import { PrerenderManifest } from 'next/dist/build'
1011

1112
const GENERIC_RSC_ERROR =
1213
'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.'
@@ -371,29 +372,28 @@ describe('use-cache', () => {
371372
})
372373

373374
it('should match the expected revalidate and expire configs on the prerender manifest', async () => {
374-
const prerenderManifest = JSON.parse(
375+
const { version, routes, dynamicRoutes } = JSON.parse(
375376
await next.readFile('.next/prerender-manifest.json')
376-
)
377+
) as PrerenderManifest
377378

378-
expect(prerenderManifest.version).toBe(4)
379+
expect(version).toBe(4)
379380

380-
expect(
381-
prerenderManifest.routes['/cache-life'].initialRevalidateSeconds
382-
).toBe(100)
383-
384-
expect(prerenderManifest.routes['/cache-life'].initialExpireSeconds).toBe(
385-
250
386-
)
381+
// custom cache life profile "frequent"
382+
expect(routes['/cache-life'].initialRevalidateSeconds).toBe(100)
383+
expect(routes['/cache-life'].initialExpireSeconds).toBe(250)
387384

388-
expect(
389-
prerenderManifest.routes['/cache-fetch'].initialExpireSeconds
390-
).toBe(31536000) // default expireTime
385+
// default expireTime
386+
expect(routes['/cache-fetch'].initialExpireSeconds).toBe(31536000)
391387

392388
// The revalidate config from the fetch call should lower the revalidate
393389
// config for the page.
394-
expect(
395-
prerenderManifest.routes['/cache-tag'].initialRevalidateSeconds
396-
).toBe(42)
390+
expect(routes['/cache-tag'].initialRevalidateSeconds).toBe(42)
391+
392+
if (process.env.__NEXT_EXPERIMENTAL_PPR === 'true') {
393+
// cache life profile "weeks"
394+
expect(dynamicRoutes['/[id]'].fallbackRevalidate).toBe(604800)
395+
expect(dynamicRoutes['/[id]'].fallbackExpire).toBe(2592000)
396+
}
397397
})
398398

399399
it('should match the expected stale config in the page header', async () => {

0 commit comments

Comments
 (0)