Closed dimasxp closed 5 months ago
Have you tried hard coding the parameters (category
, pageSize
and page
) for testing?
Could you also provide a reproduction?
Here is the reproduction. https://stackblitz.com/edit/nuxt-starter-u6ofn7?file=pages%2F%5B...page%5D.vue
I want to achieve that page 1 and page 2 are cached using SWR, so they do not trigger a load or a promise each time the page is reloaded or when switching between pages
if i right understood i cant use direct the nuxt routeRules for this
Thank you for any help 🙏
Sorry, I misunderstood. I thought that the caching of vue-query wasn't working. If you want to persist the api response data between page loads, there are numerous options:
Sadly you cannot use Nitro's built-in caching behaviour with tRPC because Nitro handles caching on a per-route basis and tRPC only uses one route (/api/trpc/[trpc]
)
Here's a pseudo caching plugin that would allow you to achieve similar behaviour as Cloudflare or Vercel:
export default defineNitroPlugin(nitro => {
nitro.hooks.hook('request', async (event) => {
// construct key from request
// look for key in cache
// if found, send cached response and return
// if not found, continue
})
nitro.hooks.hook('afterResponse', (event) => {
// construct key from request
// cache response according to cache headers if not already cached
// return response
})
})
Thank you, and sorry for my unclear explanation. Yes, I plan to deploy to Vercel and use this approach:
Just set cache headers on your API responses and use a cache proxy like Cloudflare or Vercel.
For some reason, this is not working for me. I tried to set the response headers here. https://stackblitz.com/edit/nuxt-starter-u6ofn7?file=server%2Fapi%2Ftrpc%2F%5Btrpc%5D.ts Did I miss something?
Could you share the response cache headers from your vercel preview deployment? Also take a look at this: https://vercel.com/docs/edge-network/caching#cacheable-response-criteria.
You might have other headers that prevent it from being cached (like Set-Cookie
)
Oh, yes, thanks for the link
here the response
Apparently this is due to cookies? I'm trying to figure out how to remove them for certain trpc paths
Something like this:
export function createContext(event: H3Event) {
return {
event,
}
}
export type Context = inferAsyncReturnType<typeof createContext>
export interface CacheOptions {
/**
* Max age in seconds
*/
maxAge: number
/**
* Stale while revalidate in seconds
*/
swr: number
}
const t = initTRPC
.context<Context>()
.meta<
Partial<{
cache: CacheOptions
}>
>()
.create()
export const publicProcedure = procedure.use(async ({ ctx, meta, next }) => {
if (meta?.cache) {
// don't cache in browser
setHeader(ctx.event, 'cache-control', 'no-cache')
// cache in CDN
setHeader(
ctx.event,
`cdn-cache-control`,
`public, max-age=${meta.cache.maxAge}, stale-while-revalidate=${meta.cache.swr}`,
)
} else {
setHeader(ctx.event, 'cache-control', 'no-store')
}
return next()
})
router({
hello: publicProcedure
.meta({
cache: {
maxAge: 60 * 60 * 24,
swr: 60 * 60 * 24 * 30,
},
})
.query(async ({ ctx }) => {
return 'Hello world'
}),
})
handy solution, thanks. implemented and cache now seems working in browser, loads fast but on the server side in vercel logs i see that on each page reload its still trigger long time promise.
This is probably because during SSR Nuxt directly calls the api route handlers without doing a full http request (https://nuxt.com/docs/api/utils/dollarfetch). Since it doesn't go through Vercel's caching layer, it doesn't get cached. Only fix for this would probably be to cache the whole page.
Solved. I used all your suggestions. Thanks for your help and time.
How to handle SWR cache in useQuery() to avoid fetching if the SWR cache exists?
[trpc].ts
projects.vue
pageAt the moment, each time the project page loads, it refetches