N
Nuxt4mo ago
tierra

Server API proxy caching approach

Hi all, I have a question regarding an approach to server api caching. I am using Sanity IO as a backend and I'd like to cache my server routes which is no problem. In my case right I have a filter function where a type (e.g. "posts") can be filtered with multiple tags, and I was wondering what the best approach is, because in my test queried cached routes did not work. Since the amount of filters/tags is infinite, I was thinking of a post request and not a get request. But how would I cache this route since the post req is always different/can change? One option I was thinking of is to have a cached route with all posts which then is fetched and filtered by the filtered route? Is that the correct approach? Or should I cache Route Parameters?
server/
└── api/
├── posts.get.ts // cached
└── filtered.get.ts // not cached
server/
└── api/
├── posts.get.ts // cached
└── filtered.get.ts // not cached
Whats the best way to approach this? Also the amount of posts is quite large, I am guessing around 1.000 entries Thank you!
2 Replies
manniL
manniL4mo ago
instead of caching the whole route, use defineCachedFunction with all the params needed 😋
tierra
tierraOP4mo ago
Thank you! This is what I was searching for -- will give it a shot! Would this be a correct use within Nuxt?
// utils/posts.ts
import { pageHomeUnfiltered, pageHomeFiltered } from "~~/utils/sanity.queries";

export const cachedPosts = defineCachedFunction(async (filters: string[] | undefined) => {
const sanity = useSanity();
if (filters?.length) {
// fetching filtered data
const tags = filters.toString().split(',')
return await sanity.fetch(pageHomeFiltered, { filters: tags});
} else {
// fetching unfiltered
return await sanity.fetch(pageHomeUnfiltered);
}
}, {
maxAge: 60 * 60 * 24 * 30, // 1 Month
name: 'posts',
getKey: (filters: string[] | undefined) => filters?.length ? arrayToUrlSafeString(filters) : 'allPosts'
})

function arrayToUrlSafeString(arr: string[]) {
return arr
.join(' ') // Join the array into a single string with spaces
.toLowerCase() // Convert to lowercase
.trim() // Remove any leading or trailing spaces
.replace(/\s+/g, '-') // Replace spaces with dashes
.replace(/[^a-z0-9\-]/g, '') // Remove any non-alphanumeric characters except dashes
}
// utils/posts.ts
import { pageHomeUnfiltered, pageHomeFiltered } from "~~/utils/sanity.queries";

export const cachedPosts = defineCachedFunction(async (filters: string[] | undefined) => {
const sanity = useSanity();
if (filters?.length) {
// fetching filtered data
const tags = filters.toString().split(',')
return await sanity.fetch(pageHomeFiltered, { filters: tags});
} else {
// fetching unfiltered
return await sanity.fetch(pageHomeUnfiltered);
}
}, {
maxAge: 60 * 60 * 24 * 30, // 1 Month
name: 'posts',
getKey: (filters: string[] | undefined) => filters?.length ? arrayToUrlSafeString(filters) : 'allPosts'
})

function arrayToUrlSafeString(arr: string[]) {
return arr
.join(' ') // Join the array into a single string with spaces
.toLowerCase() // Convert to lowercase
.trim() // Remove any leading or trailing spaces
.replace(/\s+/g, '-') // Replace spaces with dashes
.replace(/[^a-z0-9\-]/g, '') // Remove any non-alphanumeric characters except dashes
}
// server/api/posts.get.ts
import { cachedPosts } from "~~/utils/posts";

export default defineEventHandler(async (event) => {
const { filter } = getQuery(event)
const filters = filter?.toString().split(',')
return await cachedPosts(filters).catch(() => 0)
});
// server/api/posts.get.ts
import { cachedPosts } from "~~/utils/posts";

export default defineEventHandler(async (event) => {
const { filter } = getQuery(event)
const filters = filter?.toString().split(',')
return await cachedPosts(filters).catch(() => 0)
});
Want results from more Discord servers?
Add your server