Preset vercel: query params are ignored by cache
Environment
nitro: 2.7.0 node: v18.18.0 nuxt: 3.8.0
Reproduction
not available
Describe the bug
I use query params to figure out what page in a pagination the server should render, e.g. /?page=1
When configuring cache like this
routeRules: {
'/**': {
cache: {
swr: true,
maxAge: 60 * 60 * 48,
staleMaxAge: 60 * 60 * 96
}
}
}
vercel's cache seems to ignore the query param "page". When loading "/?page=2" I receive the cached version for "/".
This doesn't seem the be an issue with Vercel, because other pages (not nuxt/nitro) don't suffer from this issue.
So my assumption is this is an issue with nitro's vercel preset.
Additional context
No response
Logs
No response
This happens in node environment also, but only in production I believe
I can confirm this issue. And also can provide a reproduction if needed.
Also running into this. Interestingly, the issue does not appear on nuxt's vercel demo: https://nuxt-vercel-isr.vercel.app/static vs https://nuxt-vercel-isr.vercel.app/static?foobar Makes me think it might be a Vercel config issue?
I've run into this in a Vercel preview environment when trying to migrate my API endpoints from manual configuration via defineCachedEventHandler to a generic config in nuxt.config.ts:
export default defineNuxtConfig({
routeRules: {
'/api/**': {
swr: 60 * 60, // 1h
},
},
});
A bunch of API endpoints started throwing errors because they were missing a required query param. I added a log line to one of the endpoints:
console.log('query:', JSON.stringify(getQuery(event)));
This shows up in the Vercel runtime logs for each request:
// /api/grid/10/ch4-emission?ch4Threshold=1.0276462172345253e-10&period=2024-01&page%5Blimit%5D=19
query: {}
A similar request against the dev server results in:
query: {"ch4Threshold":"1.0276462172345253e-10","period":"2024-01","page[limit]":"195220"}
As an additional note to the previous comment, although my app makes several calls to the above endpoint for each view (something like paginating through a large result set with requests like ?period=2024-01 and ?period=2023-12 etc), there was only one log line with query: {} even though there were 20+ requests to the endpoint.
I would guess that setting { swr: true } in routeRules is ignoring search/query params when establishing the cache key, and therefor query params are not being sent to the request handler. This probably makes sense for static pages (lots of people visiting URLs with random google tracking rubbish like /about/?gtm_source=12321321431), but doesn't work as well for API routes.
We just got stung by this (on Vercel with isr enabled), as our paginated blog index page (?page=2, ?page=3, …) was having hydration mismatches for subsequent pages. Took quite some time to get to the root of this…
While #2375 seems promising, we're probably going to migrate the query param to a route param.
I am having the same issue but with my case, the problem is that I cannot migrate to a route param.
In my setup, we have a Nuxt 3 app deployed to Vercel and Storyblok as a CMS. Storyblok adds _storyblok query param to the url and based on that, I detect if a website is displayed in Storyblok (if so, the draft content version should be used). I tried using allowQuery: ['_storyblok'] but it does not work for me while passQuery: true results in 500 error from Vercel.
Does anyone have any other idea on how this could be acomplished?
You need to use both passQuery and allowQuery, see https://nitro.build/deploy/providers/vercel#fine-grained-isr-config-via-route-rules
E.g. for my paginated blog index page
"/blog": {
isr: {
allowQuery: ["page"],
expiration: 3600,
passQuery: true,
},
},
Do you use vercel preset or vercel-edge? In my case when I added both allowQuery and passQuery it resulted in 500 :(
I managed to make it work by instead of watching for query param to get information from the ssrContext?.event.node.req.headers.referer which works for me. Not perfect but still.
We use the vercel preset (with vercel-edge we had some issues on our stack we didn't bother looking into - but that was roughly a year ago).
You might want to open a dedicated issue for the 500 error you're seeing with some details?
Would you mind sharing the respective route rule?
We use the
vercelpreset (withvercel-edgewe had some issues on our stack we didn't bother looking into - but that was roughly a year ago).
we encountered the similar behavior:
with vercel-edge it works properly (but slower than serverless functions, as if the data wasn't located in Europe's cdn's where I'm located - not really important right now).
with vercel serverless functions enabled, the route doesn't serve the dynamic data depended on query params (filtering and stuff like that) - like the nuxt config was ignored for allowQuery setting .
I discovered that route.query is not accessible or empty - as If it was cached using a key made of only route path, without taking params into account.
when passQuery is enabled, there is an url query glued to the URL, and the 404 is being thrown.
I tried implementing an ISR cache busting middleware and adding a query param to a wildcard route (like below) triggered a 404 as well on all pages. Did you try it on a dedicated/know URL?
"/**": {
isr: {
allowQuery: ["forceRefresh"],
expiration: 3600,
passQuery: true,
},
},
I created a little nitro plugin to ensure what request comes in the serverless function:
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook("request", (event) => {
const queryParams = getQuery(event);
console.log(
"on request ----------------------",
queryParams,
event.path,
event.headers,
event.context,
event.node.req,
);
});
});
and found that the queryParams are not present inside the function - despite of being discovered by vercel gateway at the beginning (blue rectangle):
Hi all, sorry this got delayed. Finally have a runtime-safe solution for this (#3539), but appreciate any early testers to confirm if it works for your projects.
package.json
"resolutions": {
"nitropack": "https://pkg.pr.new/nitrojs/nitro/nitropack@3539"
},
Hi all, sorry this got delayed. Finally have a runtime-safe solution for this (#3539), but appreciate any early testers to confirm if it works for your projects.
package.json"resolutions": { "nitropack": "https://pkg.pr.new/nitrojs/nitro/nitropack@3539" },
great to see it working 💙 I can confirm that nitropack@3539 solves the problem 🚀
btw. for pnpm users:
// package.json
"pnpm": {
"overrides": {
instead of resolutions
@pi0 I tried with cache instead of isr using the nitropack https://github.com/nitrojs/nitro/issues/1880#issuecomment-3422670661 and I still have issues with apis having query params not returning data (or in other words query params are trimmed) . Is it expected? I saw that OP has posted about cache and not isr