mirror of
https://github.com/hanzoai/next.js.git
synced 2026-10-30 14:46:38 +00:00
Supersedes https://github.com/vercel/next.js/pull/93475 ## Summary There's a few fixes bundled in here. We're fixing `Infinity` getting serialized to `null`, which caused cache handlers and build workers to misinterpret it as "don't cache" instead of "cache forever". We use the existing infinity sentinel for that. We're also making the checks a bit more specific from `typeof !== 'number'` to forbidding `NaN` and `-Infinity`. The checks are applied consistently for profiles, inline cache life, and arguments to `fetch` and `unstable_cache`. Now that configs are also validated, we need to make sure that we only do `revalidate > expire` validation when both values are specified. There's a regression test for that, which https://github.com/vercel/next.js/pull/93475 didn't do correctly. Also, per review below: - Now actually using returned value for `unstable_cache` - Added validation + infinity fix for `revalidateTag` profile - Added validation + infinity fix in `config.experimental.staleTimes` and `config.expireTime` - Added deep clone for `defaultConfig.cacheLife` ## Test Plan New e2e tests that fail before the fixes. --------- Co-authored-by: Zack Tanner <[email protected]>
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
|
|
|
describe('expire-time-infinity', () => {
|
|
if (process.env.__NEXT_CACHE_COMPONENTS === 'true') {
|
|
it.skip('the route segment config is not compatible with cacheComponents', () => {})
|
|
return
|
|
}
|
|
|
|
const { next, skipped } = nextTestSetup({
|
|
files: __dirname,
|
|
skipStart: true,
|
|
skipDeployment: true,
|
|
})
|
|
|
|
if (skipped) return
|
|
|
|
it('serves a well-formed cache-control header for an Infinity expireTime', async () => {
|
|
await next.start()
|
|
|
|
try {
|
|
const res = await next.fetch('/')
|
|
const cacheControl = res.headers.get('cache-control')
|
|
|
|
// The stale-while-revalidate window is derived from the expireTime. An
|
|
// Infinity expireTime must resolve to a finite window instead of the
|
|
// invalid `stale-while-revalidate=Infinity`.
|
|
expect(cacheControl).toMatch(/s-maxage=60, stale-while-revalidate=\d+$/)
|
|
} finally {
|
|
await next.stop()
|
|
}
|
|
})
|
|
|
|
it('fails the build for a non-finite expireTime other than Infinity', async () => {
|
|
await next.patchFile('next.config.js', (config) =>
|
|
config.replace('expireTime: Infinity', 'expireTime: -Infinity')
|
|
)
|
|
|
|
const { exitCode, cliOutput } = await next.build()
|
|
expect(exitCode).not.toBe(0)
|
|
expect(cliOutput).toContain(
|
|
'Invalid "expireTime" provided, expected a finite number of seconds or Infinity, received -Infinity'
|
|
)
|
|
})
|
|
|
|
it('fails the build for a non-finite staleTime other than Infinity', async () => {
|
|
await next.patchFile('next.config.js', (config) =>
|
|
config
|
|
.replace('expireTime: -Infinity', 'expireTime: Infinity')
|
|
.replace('dynamic: Infinity', 'dynamic: NaN')
|
|
)
|
|
|
|
const { exitCode, cliOutput } = await next.build()
|
|
expect(exitCode).not.toBe(0)
|
|
expect(cliOutput).toContain(
|
|
'Invalid "experimental.staleTimes.dynamic" provided, expected a finite number of seconds or Infinity, received NaN'
|
|
)
|
|
})
|
|
})
|