nextjs - ✅(Solved) Fix `"use cache"`'d components do not update during HMR inside an iFrame [1 pull requests, 25 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#90143Fetched 2026-04-08 00:20:40
View on GitHub
Comments
25
Participants
3
Timeline
42
Reactions
0
Author
Timeline (top)
commented ×25subscribed ×8mentioned ×7cross-referenced ×1

Fix Action

Fixed

PR fix notes

PR #90198: fix(use-cache): fix HMR not updating in cross-origin iframes

Description (problem / solution / changelog)

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 would not 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 being sent back to the server with each HMR refresh request. The server includes this hash in the cache key of all "use cache" functions, allowing stale entries to be bypassed.

In a cross-origin iframe context, the cookie is never sent:

  1. SameSite=Lax (the browser default): cookies are blocked when the top-level context is a different site from the iframe, even for same-origin fetch requests made by the iframe's own JavaScript.
  2. "Block third-party cookies": browsers may block the cookie from 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-origin requests. 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 a next-hmr-refresh-hash request header 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 — add NEXT_HMR_REFRESH_HASH_HEADER constant
  • hmr-client-state.ts — new shared module to hold the current hash client-side
  • hot-reloader-app.tsx — set SameSite=None;Secure on HTTPS; store hash in shared state
  • fetch-server-response.ts — include hash as next-hmr-refresh-hash header when isHmrRefresh is true
  • work-unit-async-storage.external.ts — fall back to the header in getHmrRefreshHash when the cookie is not present

Changed files

  • AGENTS.md (modified, +4/-4)
  • packages/next/src/client/components/app-router-headers.ts (modified, +3/-0)
  • packages/next/src/client/components/hmr-client-state.ts (added, +18/-0)
  • packages/next/src/client/components/router-reducer/fetch-server-response.ts (modified, +11/-0)
  • packages/next/src/client/dev/hot-reloader/app/hot-reloader-app.tsx (modified, +15/-2)
  • packages/next/src/server/app-render/work-unit-async-storage.external.ts (modified, +12/-2)

Code Example

bun next info

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:48:41 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6041
  Available memory (MB): 131072
  Available CPU cores: 16
Binaries:
  Node: 22.18.0
  npm: 10.9.3
  Yarn: 1.22.22
  pnpm: 10.28.2
Relevant Packages:
  next: 16.2.0-canary.50 // Latest available version is detected (16.2.0-canary.50).
  eslint-config-next: N/A
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/rikbrown/nextjs-use-cache-in-iframe-hmr

To Reproduce

  1. Start the application in dev mode, go directly to URL.
  2. Make changes in the CacheComponent component in page.tsx, observe HMR.
  3. Now go to the page in an iFrame (either a local html file or remote - I put one in the repo)
  4. Make changes, observe no HMR
  5. HARD refresh, observe updated value,
  6. Make changes, observe no HMR.

Current vs. Expected behavior

HMR should occur without needing a hard refresh.

Provide environment information

bun next info

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:48:41 PST 2026; root:xnu-12377.81.4~5/RELEASE_ARM64_T6041
  Available memory (MB): 131072
  Available CPU cores: 16
Binaries:
  Node: 22.18.0
  npm: 10.9.3
  Yarn: 1.22.22
  pnpm: 10.28.2
Relevant Packages:
  next: 16.2.0-canary.50 // Latest available version is detected (16.2.0-canary.50).
  eslint-config-next: N/A
  react: 19.2.3
  react-dom: 19.2.3
  typescript: 5.9.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Use Cache

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

Tested on latest stable and canary.

Tested w/ "allow third party cookies off".

Verified if I manually disable caches in the chrome dev tools, HMR does work.

The crazy thing to me is if I then open the iFrame in a totally different browser, it is still out of date. But opening the exact same URL, just not in an iframe, is up to date. This is beyond my comprehension of how Next.js caches things.

extent analysis

Problem Summary Fixing HMR (Hot Module Replacement) in Next.js with useCache in an iFrame.

Fix Plan

  1. Disable caching in Next.js: Add the following code to next.config.js:
module.exports = {
  // ... other configurations ...
  experimental: {
    disableCache: true,
  },
};
  1. Use useEffect with useCache: Update the CacheComponent component in page.tsx to use useEffect with useCache:
import { useCache } from 'next/use-cache';

function CacheComponent() {
  const [value, setValue] = useCache('my-cache', 0);

  useEffect(() => {
    setValue(Date.now());
  }, []);

  return <div>Value: {value}</div>;
}
  1. Enable HMR in Next.js: Make sure HMR is enabled in your next.config.js file:
module.exports = {
  // ... other configurations ...
  devOptions: {
    hot: true,
  },
};

Verification

  1. Start the application in dev mode.
  2. Make changes in the CacheComponent component and observe HMR.
  3. Open the page in an iFrame and make changes; HMR should occur without needing a hard refresh.

Extra Tips

  • Make sure to clear the cache in the browser by pressing Ctrl + Shift + R (Windows/Linux) or Cmd + Shift + R (Mac) after making changes to the CacheComponent component.
  • If you're still experiencing issues, try disabling caching in the browser by pressing F12 (Windows/Linux) or Cmd + Opt + I (Mac) and then disabling caching in the DevTools.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - ✅(Solved) Fix `"use cache"`'d components do not update during HMR inside an iFrame [1 pull requests, 25 comments, 3 participants]