RSC payload served from browser disk cache after router cache is cleared by a mutation #97485
Replies: 4 comments 2 replies
|
I've been able to repro this, let me do a bit more of triaging, I'll share it internally too. |
|
Likely cause: |
|
The difference in behavior comes down to how browser HTTP caching interacts with Next.js Client Router Cache versus Server Action redirects: 1. Why
|
|
Here is the breakdown of what is happening under the hood with Next.js 16, the browser disk cache, and why 1. Why
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Config:
The problem is:
Let's say I'm on a route '/todolist' which displays a todolist that includes a couple of todolist items, fetched from the database using a 'use cache' cached function which assigns a tag 'todolist' to this cache. I do a soft navigation from the '/todolist' to the '/todolist/[id]' route in order to update the todolist item via a server action, and then I do
updateTag('todolist')at the very end of it. I'm using a client-side form component, so I do a redirect back withrouter.push('/todolist')inside an event handler after a successfull mutation. It works exactly once, because after the first mutation the browser caches the previousrouter.push('/todolist')server 'rsc' response. So from now on I have this sequence of events, I guess:server action (success) ->
router.push('/todolist')call -> event handler is done running / urgent state updates are finished -> router cache is being purged due to theupdateTagcall (link prefetching starts, if any) -> soft-navigation to the '/todolist' route -> browser requests the '/todolists' page from the server checking its cache first, and finding the previously cached 'rsc' in there (I seeStatus Code 200 OK (from disk cache)for this request) -> 'rsc' is being stored in the router cache -> I see unupdated todolist after the navigation.What fixes this issue:
headers()/proxyfor this route when a 'rsc' request is commingrevalidatePath('/todolist')+redirect('/todolist')in the server action instead of the previous setup. I don't know why this works either, in this context callingrevalidatePathandupdateTagmust have no difference, and callingredirectfrom the server action also just makes a client-side navigation after the promise rejects in the event handler. The only difference that I spotted is that server response that happens after the navigation withrevalidatePath('/todolist')+redirect('/todolist')doesn't have a 'stale-while-revalidate' header. I'm not a huge browser cache expert, so I cannot tell if this is the root of the problem or notThe questions are:
updateTag+router.pushdoesn't work properly?updateTag+router.pushdifferent from therevalidatePath+redirectcombination?updateTag+router.pushwhen the browser gets a cached response from the disk cache? is it some soft of SWR but in the browser itself?All reactions