Does anyone have a good way to avoid opting out of caching when reading headers/cookies?
Unanswered
Northeast Congo Lion posted this in #help-forum
Northeast Congo LionOP
If you have an app that uses cookies/headers to render something SSR with NextJS using the app router, is there any way to get NextJS to not opt out that route from setting the Cache-Control response header to something that allows caching?
From what I understand, if you use a dynamic function within a route, Next will opt you out of caching and there's no way to tell it that you can cache responses using one of those headers/cookies as part of the cache key, knowing that your response is unique to that value.
Is this just something that can't be done with NextJS?
From what I understand, if you use a dynamic function within a route, Next will opt you out of caching and there's no way to tell it that you can cache responses using one of those headers/cookies as part of the cache key, knowing that your response is unique to that value.
Is this just something that can't be done with NextJS?
48 Replies
Northeast Congo LionOP
Bumping this question in the hopes that I can get some insight!
Northeast Congo LionOP
Bumping again to hopefully get some advice!
How do you plan to use the headers in static routes? It just doesnt make any sense
Northeast Congo LionOP
Thanks for the reply @aardani ! I'm planning on using them for a rewrite of a Django site that currently uses the header as part of the cache key in CloudFront.
So, the current Django app will render a page that uses a value from the Host header to determine the kind of page it's gonna render, then sets a
Cache-Control value that allows for caching and a Vary value that includes the Host header. In this setup, the same route can render multiple pages (which are just slightly different flavors of the same page), keying off the Host header to stamp them out. Downstream caching also respects that the Host header is used as part of the cache key.As we look to rewrite the Django app in NextJS, it looks like there's no way to get the same functionality, as we can't explicitly set the
Cache-Control value with the app router, and if we do some middleware logic to render using a dynamic route based on the header value, we'll have to build all the dynamic routes at build time using generateStaticParams.Is the issue that we're not realizing functionality available in NextJS to meet our needs, or are we trying to build something that isn't compatible with how NextJS renders apps?
Northeast Congo LionOP
Ideally, we'd be able to have the same render pattern, where we can render the page based on the
Host header, then explicitly set the Cache-Control value, or set an allow-list of headers that can be accessed in a route without opting out of having NextJS set the Cache-Control header due to the call to a dynamic function.In Next.js, the server overrides any kind of incoming Cache Control header . The rendering system is completely taken care by next.js
Northeast Congo LionOP
The host is the server, I think an example might clear it up
HTTP request with Host: `abc` --> NextJS at route `/`
HTTP request with Host: `def` --> NextJS at route `/`As far as I've been able to work out, there's no way to tell NextJS "I know you might render two different types of pages at the index route on request. That's OK. Please set the
Cache-Control header on the response to indicate that that response is cacheable, as we're going to cache those responses with the Host header as part of the cache key."The same server as your django app? Or another server
Northeast Congo LionOP
The NextJS app is gonna be hosted on its own server
We're just trying to mirror what currently happens in Django, if possible.
I know
But i dont quite fully understand your use case. Where do you get the header at build time?
Theres no user at build time hence theres no way to get header or cookie or request object at build time
Northeast Congo LionOP
I agree. Given my current understanding of the way that the app router works right now, we'd have to use middleware to extract the
Host header and use it as part of a dynamic route that can use generateStaticParams to build out all the requisite pages that any given Host value that might be used as part of a request.In the Django app, we can read the
Host header in the entry point to render the page on-the-fly, and set the response headers to include the Cache-Control value.So I'm just wondering if there's a way to have it so that the list of possible valid
Host values aren't determined at build time (the list of supported Host values changes dynamically), while still setting the Cache-Control value in the repsonse.@Northeast Congo Lion
HTTP request with Host: `abc` --> NextJS at route `/`
HTTP request with Host: `def` --> NextJS at route `/`
Isnt this just requesting to /abc and /def?
@aardani Isnt this just requesting to /abc and /def?
Northeast Congo LionOP
Assuming we use the middleware workaround where we have a dynamic route for each supported host header, and use
generateStaticParams to build out those routes, ya. Internally, the requests will be routed to /abc and /def, but externally, requests will be made to / with Host header abc or defThe staticity of Next.js routes is only determined at build time. It canmot detect at runtime whether a route should be static or dynamic
Furthermore the staticity of the route is also not dependent of external factors such as middleware or the users. Its is purely based on the usage of dynamic features on which it is determined at build time
Therefore im not sure what you want to make is possible or not.
But probably the behavior can be replicated to closely mimick what you have before
Northeast Congo LionOP
OK, well thank you for taking a look at this! Do you know if there's a good place for me to try to get more input on this?
Currently, the solution my team is looking to implement is to just ignore the
Currently, the solution my team is looking to implement is to just ignore the
Cache-Control response set by NextJS and override the value with an NGINX container running between the client and the NextJS server. This doesn't seem like the best way to address this problem to me, though. It feels like it's a gap in our understanding of what NextJS can do.Let me understand this. You have two host like www.a.com and www.b.com that points to the same Next.js server and you want to set different caching between these two host for a single route?
Northeast Congo LionOP
Ya
@Northeast Congo Lion Ya
Does www.a.com and www.b.com points to a different route like server:3000/a and server:3000/b or do they both access the same route like '/'
Northeast Congo LionOP
They both access the same route
Hmm thats hard
I think this is possible with dynamically computed routes using data cache instead of full eouter cache
But i doubt ure into rendering at request time solution (while caching some other part)
Using unstable_cache() you can set whether or not you want to cache the data or just skip the cache
Northeast Congo LionOP
Ooooh
Would that allow the response header to be set appropriately?
We need the HTTP response cached downstream
I am not sure about the response headers
Northeast Congo LionOP
It seems like
unstable_cache() is also an experimental API that's not ready for production yet 😦Yep, you can still use fetch to fetch your own api for that
It works the same way
Northeast Congo LionOP
Sorry, I don't follow that
Create an api endpoint in nextjs,
From server component, fetch to your own endpoint to enable the data caching behavior
From server component, fetch to your own endpoint to enable the data caching behavior
Northeast Congo LionOP
Ah, I see what you're saying. Ya, I think that would be better than not caching at all, but it still wouldn't let us have NextJS set the
Cache-Control header on the response, because we would need to extract the Host header using a dynamic function to send it to the API endpoint, which would opt us out of caching (for the route*).Would a good next step for me to take be to create a feature request on the NextJS GitHub, or do you know if this isn't the kind of functionality that NextJS wants to support?