Open gaearon opened 2 years ago
Originally, we added that behavior in #24189 to support query parameters in rewrites
:
{
source: '/rewriting-to-auto-export',
destination: '/auto-export/hello?rewrite=1',
},
...which is a valid use case. I’m wondering that if it makes sense to only trigger the router's subscription if the state doesn't change (with deep comparison): https://github.com/vercel/next.js/blob/f9ed7954bf151bcace8cf731d29f537c1d164103/packages/next/shared/lib/router/router.ts#L1670-L1682
This may not be directly related to rewrites, causing unnecessary re-renders at the top level, but for re-renders in general.
The linked issue describes the problem of changing the hash of a route, which per se should not result in a re-render of the entire app starting in _app. Indeed, it is a change made to the router context; it seems only a single property "asPath" changes. Re-render from the top is too expensive for inner page navigation, which should be as lightweight as possible.
Maybe the linked issue can also be addressed to solve the current problem.
Since the hash is part of the router context I don’t think it could be updated independently. But the suggestion to do a comparison first makes sense to me.
Reopening since the change was reverted.
hi, is there any update or ongoing/planned work on this?
Verify canary release
Provide environment information
What browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
Describe the Bug
If you have
rewrites
in next config:Then Next.js will cause a top-level re-render right after the initial navigation:
https://github.com/vercel/next.js/blob/e57e2753f12076a99173a80787e6d1a2cdb3a0fc/packages/next/client/index.tsx#L118-L121
This has negative performance implications (if you don't have a bunch of memos, it may render the entire app twice 🙃 ), and can lead to cascading updates in userland effects which in turn may cause Suspense boundaries to get dehydrated (https://github.com/vercel/next.js/pull/33861#issuecomment-1135071203).
Expected Behavior
I would not expect Next.js to call
replaceState
on every single initial navigation for every page if I have definedrewrites
in my config. (I only usedrewrites
for the RSS feed.) It is not obvious that just havingrewrites
in the config degrades the perf of every page in the application. In either case, even ifreplaceState
is called, I would not expect the router component to propagate a context update if nothing in the route context actually changed (the path is the same, etc).To Reproduce
Here's the branch:
https://github.com/gaearon/sc-bug-repro/tree/render-twice
yarn
,yarn build
,yarn start
.Notice that in production the effect runs twice. However, it should run once because there is no reason for the second render in production. If you remove
rewrites
from the config, it will run once as expected.