When I run next build
, newly fetched data is not being served to the client, even though the fetch call is hitting my server. I can solve the problem by using {cache: "no-store"} in my fetch requests, but that turns my SSG pages into SSR which I don't want.
Nextjs version: 13.5.2 (app router)
next build
next start
Result: I can see fetch hitting my CMS, but the fresh data is not displayed. This persists over multiple builds.
Example code (simplified):
/articles.ts
export async function getArticleBySlug(slug){
try {
const res = await fetch(path, { method: GET })
return await res.json()
} catch (error) {
console.log(error)
return null
}
}
[slug]/page.tsx
export default async function Article({ params }) {
const article = await getArticleBySlug(params.slug)
return <div>{article.data}</div>
}
From my research, it seems like the Nextjs Data Cache is the culprit here. The docs say the data cache is persisted between deployments, which is a feature I don't want. I want the cache to be completely invalidated on every build, while maintaining SSG.
A funny solution to this seems to be having my fetch calls be larger than 2MB. That way the cache is unable to be set but SSG is preserved. Forcing all of my requests to be larger than 2MB is definitely not the solution, so other ways of solving this would be greatly appreciated! Another janky solution would be setting the cache invalidation limit to something really low, but that also seems wrong.
It's very possible I'm diagnosing my problem incorrectly, but I can't seem to find any other reason why stale data would be populating my site.
Thank you for the help!!
I ended up following this discussion post https://github.com/vercel/next.js/discussions/48324 and setting the get()
method of Next's IncrementalCache
to return early, and the data threshold of the set()
function to be very low, effectively skipping them entirely. Not sure if next hits those caches any other time, especially if my entire site is static so I think this solution should be fine.
node_modules/next/dist/esm/server/lib/incremental-cache/index.js & node_modules/next/dist/server/lib/incremental-cache/index.js
// get data from cache if available
async get(cacheKey, ctx = {}) {
return null;
...
}
async set(pathname, data, ctx) {
...
if (ctx.fetchCache && JSON.stringify(data).length > 0.001 * 1024 * 1024) {
if (this.dev) {
throw new Error(`fetch for over 0.001MB of data can not be cached`);
}
return;
}
...
}