Skip to content

Commit ac1dbb1

Browse files
committed
bugfix: static resources staleTime should be renewed once refetched
1 parent 3a5d293 commit ac1dbb1

File tree

2 files changed

+74
-18
lines changed

2 files changed

+74
-18
lines changed

packages/next/src/client/components/router-reducer/prefetch-cache-utils.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -404,22 +404,7 @@ function getPrefetchEntryCacheStatus({
404404
kind,
405405
prefetchTime,
406406
lastUsedTime,
407-
staleTime,
408407
}: PrefetchCacheEntry): PrefetchCacheEntryStatus {
409-
if (staleTime !== -1) {
410-
// `staleTime` is the value sent by the server during static generation.
411-
// When this is available, it takes precedence over any of the heuristics
412-
// that follow.
413-
//
414-
// TODO: When PPR is enabled, the server will *always* return a stale time
415-
// when prefetching. We should never use a prefetch entry that hasn't yet
416-
// received data from the server. So the only two cases should be 1) we use
417-
// the server-generated stale time 2) the unresolved entry is discarded.
418-
return Date.now() < prefetchTime + staleTime
419-
? PrefetchCacheEntryStatus.fresh
420-
: PrefetchCacheEntryStatus.stale
421-
}
422-
423408
// We will re-use the cache entry data for up to the `dynamic` staletime window.
424409
if (Date.now() < (lastUsedTime ?? prefetchTime) + DYNAMIC_STALETIME_MS) {
425410
return lastUsedTime

test/e2e/app-dir/app-prefetch/prefetching.stale-times.test.ts

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,11 @@ describe('app dir - prefetching (custom staleTime)', () => {
137137
let requests: string[] = []
138138

139139
browser.on('request', (req) => {
140-
// only consider requests that have RSC header but not the prefetch header
141-
if (req.headers()['rsc'] && !req.headers()['next-router-prefetch']) {
142-
requests.push(new URL(req.url()).pathname)
140+
const path = new URL(req.url()).pathname
141+
const headers = req.headers()
142+
143+
if (headers['rsc']) {
144+
requests.push(path)
143145
}
144146
})
145147

@@ -164,4 +166,73 @@ describe('app dir - prefetching (custom staleTime)', () => {
164166
).toHaveLength(1)
165167
})
166168
})
169+
170+
it('should renew the stale time after refetching expired RSC data', async () => {
171+
const browser = await next.browser('/404')
172+
let requests: string[] = []
173+
174+
browser.on('request', (req) => {
175+
requests.push(new URL(req.url()).pathname)
176+
})
177+
178+
// Navigate to home and wait for static page to be prefetched
179+
await browser.eval('location.href = "/"')
180+
181+
await retry(async () => {
182+
expect(
183+
requests.filter((request) => request === '/static-page')
184+
).toHaveLength(1)
185+
})
186+
187+
// Navigate to static page (should use cached data)
188+
await browser
189+
.elementByCss('#to-static-page')
190+
.click()
191+
.waitForElementByCss('#static-page')
192+
193+
// Go back to home
194+
await browser
195+
.elementByCss('#to-home')
196+
.click()
197+
.waitForElementByCss('#to-static-page')
198+
199+
// Wait for stale time to expire (10 seconds)
200+
await waitFor(10000)
201+
202+
// Navigate to static page again (should refetch due to expired cache)
203+
await browser
204+
.elementByCss('#to-static-page')
205+
.click()
206+
.waitForElementByCss('#static-page')
207+
208+
// Verify that refetch happened
209+
await retry(async () => {
210+
expect(
211+
requests.filter((request) => request === '/static-page')
212+
).toHaveLength(2)
213+
})
214+
215+
// Go back to home
216+
await browser
217+
.elementByCss('#to-home')
218+
.click()
219+
.waitForElementByCss('#to-static-page')
220+
221+
// Wait less than the stale time (5 seconds - should still be fresh)
222+
await waitFor(5000)
223+
224+
// Navigate to static page again (should NOT refetch - stale time should be renewed)
225+
await browser
226+
.elementByCss('#to-static-page')
227+
.click()
228+
.waitForElementByCss('#static-page')
229+
230+
// This should still be 2 - no new request should have been made
231+
// If this fails, it means the stale time was not renewed after the refetch
232+
await retry(async () => {
233+
expect(
234+
requests.filter((request) => request === '/static-page')
235+
).toHaveLength(2)
236+
})
237+
})
167238
})

0 commit comments

Comments
 (0)