Middleware affecting getInitialProps after 12.2.0
See original GitHub issueVerify canary release
- I verified that the issue exists in the latest Next.js canary release
Provide environment information
Operating System: Platform: linux Arch: x64 Version: #44~20.04.1-Ubuntu SMP Fri Jun 24 13:27:29 UTC 2022 Binaries: Node: 14.17.5 npm: 6.14.14 Yarn: 1.22.17 pnpm: 6.32.1 Relevant packages: next: 12.2.3-canary.17 eslint-config-next: 12.2.3 react: 18.2.0 react-dom: 18.2.0
What browser are you using? (if relevant)
Brave
How are you deploying your application? (if relevant)
self hosted (locally)
Describe the Bug
hello,
I have an app that has a _app.js with a getInitialProps
, but also some other pages that still have getInitialProps
implemented.
After updating to Next.js 12.2 we are noticing that the presence of the middleware file makes it so that these getInitialProps
run both on client and server always (first the sever then the client), removing the middleware file restores the old behaviour where the getInitialProps
runs only on the client when doing a client transition and on the server when doing a server reload
this feels a bit at odds with the documentation on getInitialProps
https://nextjs.org/docs/api-reference/data-fetching/get-initial-props “For the initial page load, getInitialProps
will run on the server only. getInitialProps
will then run on the client when navigating to a different route via the next/link component or by using next/router” -> The page in question does not implement getServersideProps
(but I do have a getInitialProps
in _app.js
as described above)
My question is : Is this intentional behaviour? that adding a middleware affects how the getInitialProps
function behaves? And was this meant to be introduced in 12.2? I understand that middleware was not stable before and so there are changes to it that were to be expected but since this behaviour is not documented I was wondering if this is indeed intentional or not.
Here are 2 videos of a bare bones next app demonstrating the issue :
Without any middleware
Without any middleware the behaviour we can see is that getInitialProps
works as documented, when doing a server load it runs on th server and when doing a client transition it runs on the client
https://user-images.githubusercontent.com/2866604/180443142-d664c9eb-490a-4319-b185-02ffefff1ebe.mp4
With middleware
With middlware we can see that for the same app the behaviour changes, and it now runs always on server and client even when doing client transitions (where previously it would only run on the client)
https://user-images.githubusercontent.com/2866604/180443276-b6176885-0fab-43e5-95a0-35b8e413346e.mp4
Here is the repo reproducing the problem
https://github.com/joaogarin/middleware-gip
Thank you!
Expected Behavior
I would expect the getInitialProps
to run as documented : If doing a client transition it runs in the client otherwise if doing a full load it runs on the server, but not both.
Link to reproduction
https://github.com/joaogarin/middleware-gip
To Reproduce
yarn install && yarn dev
- see the logs n the console. even if doing a client side transition the getInitialProps
is being called twice both on the server and client
This also happens in a build application (with yarn build)
Issue Analytics
- State:
- Created a year ago
- Reactions:9
- Comments:12 (4 by maintainers)
Top GitHub Comments
I did take me quite some time to investigate this behaviour today. Can we at least document that
getInitialProps
will run on the server for every request if you also have a middleware?It’s quite interesting to see a request being made from the browser to a
.json
file which then responds with the fully server-rendered html page. Is that really necessary ? What is happening with that information on the client?ahhh fair enough, that all makes sense then, thanks for taking the time to answer my questions!
our solution for now will be to do something like
if (!context.req || context.asPath?.startsWith('/_next/data/')) { ... }
ingetInitialProps
to try to short-circuit this. Possibly in the future might try doing something with a shallowrouter.push
and replicate our middleware logic to the client, though that also seems tough.