fix(use-cache): fix HMR not updating in cross-origin iframes#90198
Open
lllomh wants to merge 6 commits intovercel:canaryfrom
Open
fix(use-cache): fix HMR not updating in cross-origin iframes#90198lllomh wants to merge 6 commits intovercel:canaryfrom
lllomh wants to merge 6 commits intovercel:canaryfrom
Conversation
vercel#90133)" This reverts commit 527ae19.
Collaborator
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
1 similar comment
Collaborator
|
Allow CI Workflow Run
Note: this should only be enabled once the PR is ready to go and can only be enabled by a maintainer |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a Next.js app is embedded in a cross-origin iframe (e.g. behind an
HTTPS tunnel like cloudflared or ngrok),
"use cache"components wouldnot update during HMR. A hard refresh was required to see changes.
Fixes #90143
Root Cause
HMR cache-busting relies on a
__next_hmr_refresh_hash__cookie beingsent back to the server with each HMR refresh request. The server includes
this hash in the cache key of all
"use cache"functions, allowing staleentries to be bypassed.
In a cross-origin iframe context, the cookie is never sent:
top-level context is a different site from the iframe, even for
same-origin fetch requests made by the iframe's own JavaScript.
being set or read entirely in cross-site iframe contexts.
Without the hash, the server returns the old cached value. Because this is
a server-side cache, the stale result is returned to all clients — which
explains why even a completely different browser would see outdated content.
Fix
Two-layer approach:
1. SameSite=None cookie on HTTPS
When the dev server is served over HTTPS, the cookie is now set with
SameSite=None; Secure, which allows it to be transmitted in cross-originrequests. This fixes the common tunnel setup (cloudflared, ngrok, etc.)
for browsers that allow third-party cookies.
2. Request header fallback
The current hash is also stored in a module-level variable
(
hmr-client-state.ts) and sent as anext-hmr-refresh-hashrequestheader on every HMR refresh fetch. The server now checks this header as a
fallback when the cookie is absent. This covers environments where
third-party cookies are blocked entirely.
Changes
app-router-headers.ts— addNEXT_HMR_REFRESH_HASH_HEADERconstanthmr-client-state.ts— new shared module to hold the current hashclient-side
hot-reloader-app.tsx— setSameSite=None;Secureon HTTPS; storehash in shared state
fetch-server-response.ts— include hash asnext-hmr-refresh-hashheader when
isHmrRefreshis truework-unit-async-storage.external.ts— fall back to the header ingetHmrRefreshHashwhen the cookie is not present