After having upgraded to v9 this morning we noticed that CSP was failing. Upon further investigation, it turned out that ctx.req
and ctx.res
were returning undefined
in _document.js
(or .ts) when calling getInitialProps
.
This has been reproduced by combining the basic custom-document example as well as the custom-server example.
https://codesandbox.io/s/next9-getinitialprops-bug-f1lj7
req
and res
should have content.
Server logs:
Hey @frankrobert-ls! This is because the page is being statically prerendered -- we should improve the documentation around this. 馃槃
We'll double check this is working as expected, too.
@Timer Thanks for responding so quickly! If this is working as intended (as I understood from your response), is there a proposed workaround or alternative solution to getting access to server-side properties?
@frankrobert-ls since the page is statically prerendered _document
"middleware" (i.e. getInitialProps) will not run when deployed to production -- that's why req
and res
is undefined in this case (to emulate prod during dev).
The _document
will only be used for its custom rendering function.
If you'd like to force the page to server-side render (so you can use GIP/middleware), you'll need to add a stub getInitialProps
to your page -- this causes Next.js to de-optimize (disable) this performance feature.
It seems like a custom _document getInitialProps
should disable the feature just like _app's does.
@exogen it should not. getInitialProps in _document is also the rendering pipeline so everyone needs to have in their _document. It would deopt pretty much every Next.js application in existence as most css-in-js solutions need access to this specifically.
In case you want to opt-out for the whole application you can add _app.js with a getInitialProps method.
True, I think the surprising part is that the default assumption is the unsafe backwards-incompatible one (assume they aren't using req/res in their Document.getInitialProps
) vs. the safe backwards compatible one (assume they could be using those and provide a way to opt into prerender).
@exogen this is why it was released behind a major version, i.e. 9.0.0
.
We made the decision to be fast by default instead of relying on the user to remember to prerender a page.
Adding a check to see if req
or res
is undefined seems like a small price to pay for massive performance gains. 馃槃
@Timer I am facing the same problem. I got this
since the page is statically prerendered _document "middleware" (i.e. getInitialProps) will not run when deployed to production -- that's why req and res is undefined in this case (to emulate prod during dev).
I would like to know what should I do to make _document.js to force server side render and how? I'm new to nextjs.
I am facing the same problem too. is there any workaround?
This would be particularly helpful for setting the lang
on the <Html>
tag. I'd like to see in the request what domain name is being used (.com
, .nl
, .pt
, etc.) and determine the appropriate fallback language from that. :)
@rahadkc @derakhshanfar
The documentation added by that commit above is reflected here:
https://nextjs.org/docs/advanced-features/automatic-static-optimization#caveats
In practice, req
/res
will be undefined in your _Document as long as the app is being statically rendered, which is the default behaviour when your application omits getInitialProps
in any of your pages.
A way around this is to add a getInitialProps
call to your _App, and static rendering will no longer block the req
/res
response in _Document. The downside of this method means that you'll be forgoing static rendering on -any- pages, so as a happy medium I just getInitialProps
on the pages I need to SSR and let static rendering handle the rest.
Most helpful comment
@exogen it should not. getInitialProps in _document is also the rendering pipeline so everyone needs to have in their _document. It would deopt pretty much every Next.js application in existence as most css-in-js solutions need access to this specifically.
In case you want to opt-out for the whole application you can add _app.js with a getInitialProps method.