Pages Router hydration causes an extra client render on full page load when any rewrite is configured, including non-rewritten routes
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 142k
- Forks
- 32.5k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 351
Description
Link to the code that reproduces this issue
https://github.com/gurkerl83/next-pages-router-global-rewrite-rerender-repro
To Reproduce
- Clone the linked reproduction.
- The reproduction configures exactly one rewrite:
/rewritten -> /target. - Run:
pnpm install
pnpm build
pnpm start
- Open
/directly in the browser, or reload/. - Open
/rewrittendirectly in the browser, or reload/rewritten. - Check the browser console.
Observed result:
_applogs two client renders on/_applogs two client renders on/rewritten
Important notes:
- This does not reproduce in
next dev. - Client-side navigation with
<Link>is not the repro path here. - The extra render happens during the initial browser hydration path on a full page load or reload.
- The rendered pages do not use
useRouter(). - The on-page render counters use plain React refs.
_appreadsRouter.routeronly for logging.
Current vs. Expected behavior
Current behavior:
In the linked reproduction, the app has one rewrite: /rewritten -> /target.
On a full page load or reload in production:
/rewrittengets an extra client render/also gets an extra client render, even though/is not rewritten
Expected behavior:
I am not asking to remove rewrite-aware hydration reconciliation entirely.
I would expect the extra Pages Router hydration rerender to happen only when the current request actually depends on rewrite-derived route or query reconciliation.
So in this reproduction, I would expect:
/rewritten: rewrite-specific reconciliation if needed/: a single client render
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:54:55 PST 2026; root:xnu-12377.91.3~2/RELEASE_ARM64_T6031
Available memory (MB): 65536
Available CPU cores: 16
Binaries:
Node: 22.6.0
npm: 10.8.2
Yarn: 1.22.22
pnpm: 10.18.1
Relevant Packages:
next: 16.3.0-canary.2 // Latest available version is detected (16.3.0-canary.2).
eslint-config-next: N/A
react: 19.2.5
react-dom: 19.2.5
typescript: 6.0.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Pages Router, Linking and Navigating
Which stage(s) are affected? (Select all that apply)
next build (local), next start (local)
Additional context
I verified this on the latest canary: 16.3.0-canary.2.
This seems related to the older closed issue:
That issue was closed as expected behavior because rewrites may require a post-hydration query update for static pages. This reproduction shows a narrower problem: the same extra rerender also happens on /, even though / is not rewritten.
The reproduction is intentionally minimal:
- one rewrite:
/rewritten -> /target /is static and not rewritten- the rendered pages do not use
useRouter() _apponly logsRouter.routerstate for debugging
So the issue here is not just “rewritten routes rerender”, but that the presence of any rewrite appears to trigger the hydration rerender path for unrelated static routes too.
What I think should happen instead:
- keep rewrite-aware hydration reconciliation for requests that actually need it
- avoid the extra hydration rerender for requests whose effective route identity and query are already correct
This reproduction is meant to show that the current trigger appears to be app-global, while the behavior should be request-local.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked reproduction and inspect the Pages Router hydration path exercised by the _app render logs. Run pnpm install, pnpm build, and pnpm start, then compare direct loads of / and /rewritten in the browser console. Done means rewrite reconciliation remains for routes that need it while / has one client render on a production load.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, next.js, react
- Domain
- frontend, web-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100