Closed Javad9s closed 6 days ago
Facing the same issue
I'm encountering issues with data revalidation using the revalidateTag option. I'm fetching the site name from the database to display it in sidebars and headers. However, when I modify the site name within the Settings form and use revalidateTag upon submission, the updated data is only reflected on the Settings page itself, not on other pages.
I'm encountering issues with data revalidation using the revalidateTag option. I'm fetching the site name from the database to display it in sidebars and headers. However, when I modify the site name within the Settings form and use revalidateTag upon submission, the updated data is only reflected on the Settings page itself, not on other pages.
sorry it does not work for you, but at least you helped me out with my caching issue, thanks! :)
I'm encountering issues with data revalidation using the revalidateTag option. I'm fetching the site name from the database to display it in sidebars and headers. However, when I modify the site name within the Settings form and use revalidateTag upon submission, the updated data is only reflected on the Settings page itself, not on other pages.
Actually I've noticed your comment in additional context part [2], from original post. But i'd interpreted it as a bug, sure in my reproduction the 'control panel' reflects the changes but since it is a static pages it shows the stale page again with next reload.
Not Fixed, Just tested with 14.1.1-canary.1.
I've been having this problem with 13.5.6 too.
Same issue persists using 14.1.0. Works fine locally, but Vercel is not reliable.
Facing this same issue as well on 14.1.0. If I remove generateStaticParams
from the page, works as expected. However, if I use generateStaticParams
and revalidate the tag used on that page the cached page is hit resulting in showing stale data (after revalidation has occured).
having the same issue when revalidating the color of a theme. the theme provider is in the root layout of a [domain]
path. everything works fine on the /
route but on all the sub routes the color stays the same after revalidation. As @alexknipfer mentinoned without generateStaticParams
everything works as expected.
I found a reddit thread that mentioned a similar issue where
export const dynamic = "auto"
fixed the issue. This also worked in my case:
here's the thread https://www.reddit.com/r/nextjs/comments/14iu6td/revalidatepath_not_updating_generatestaticparams/
Edit: as @lmounsey mentioned this disables the static cache and does not fix the issue
@chrishoermann I came across that post as well, I’m assuming your snippet above was referring to dynamic
and not revalidate
? I’m surprised that works because I thought that was already the default value. https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic
I’d have to retest with my what I’m working on, but I thought when I set dynamic to auto it would cause a refetch of the page every request and not serve a cached page.
I've done some initial testing and the fix above seems to have resolved it, I'll need to do some further testing and report back.
One thing I did notice though is the response header X-Vercel-Cache
value is MISS
on all pages - response time is 300-500ms compared to 60ms.
I found a reddit thread that mentioned a similar issue where
export const revalidate = "auto"
fixed the issue. This also worked in my case:
You would never actually know what nextjs will do in production =D .
But as far as I know this is equivalent to export const dynamic = "force-dynamic"
in most cases, and is not a magical keyword. So you are just making your pages dynamic. If that's good for your case then congrats.
Anyways the original post where never about generateStaticParams()
. It might be problems with Vercel edge network, Vercel CDN, Vercel cache, cache control headers or build pipeline.
@lmounsey yeah I noticed the same 😞
@Javad9s you'r right, its not generally about generateStaticParams()
but to my understanding this should be equivalent to const dynamic = "force-static" / "error"
and therefore to pre-rendering during build time. Sadly it does not work to revalidate these pages with the methods mentioned in the docs (revalidate cache tag) or I'm just to stupid to read it the right way.
But as you mentioned nextJs with app dir is kind of a surprise package in production. The more I work with the app directory, the more I get frustrated by the DX - expecially with the whole caching stuff - and the more I regret I started using it in my current project. 😭
I have the same issue too: as @alexknipfer said removing the generateStaticParams
it works like expected even if the page is not statically prerendered but server-rendered; fortunately if I set the revalidate
properties to false
my server calls are cached and revalidated on-demand only.
Hi, any news about this issue? Without using the generateStaticParams
is very frustrating because I need to deal manually with non existing pages and every page is not statically served with an unnecessary resource usage. Thanks!
Reading the doc I think that this is an expected behavior:
During revalidation (ISR), generateStaticParams will not be called again.
The main difference with the blocking
fallback option in the pages routing system, is with app routing you can't pre-generate pages on build that then you want revalidate too.
Hey @valse
I was starting to think that too, but shouldn't the expected behaviour be similar to getStaticPaths
using the pages
router?
Also, on local dev the ISR using generateStaticParams
works fine, it's just when deployed to Vercel the issue occurs. I can also get revalidatePath
to work on Vercel sometimes however I can't replicate repeatedly the conditions to make it work/not work. But I'm thinking therefore it is a current bug with Vercel/Next.js.
I'm hoping this gets rectified soon otherwise I may have to start doing new projects using the pages
router.
Hi @lmounsey, I tried a solution from a @leerob repo about revalidating static pages on demand and it works: the page is statically rendered, cached and revalidated.
You must add the force-static
dynamic option, set dynanicParams
to true
and returns an empty array from the generateStaticParams
method generating all the static pages at runtime.
The issue for the pre-builded pages still exist but the result is quite the same 😅
I have this same issue in Next 14.1. All my pages are prerendered on the Vercel build. Many of the pages have lists or drop downs built using the results from a DB call. This DB call uses unstable_cache. There is also a page for adding to or editing the DB. The server action for adding/editing calls revalidateTag(). When I build locally the dropdowns and table are updated after revalidateTag() is called, but on the Vercel build this is not the case. If I make the pages dynamic, the dropdowns and tables are updated after adding/editing. However, I would prefer not to do this as the adding/editing doesn't take places often.
I am also encountering this issue: I have a static route which gets revalidated in dynamic route. wWhen I go to the static page again it's the same. Only rebuild updates the static page.
For now, I'll be forcing to page into dynamic.
Hi, the stale cache reads on first request after a revalidation was a confirmed issue that has since been resolved and appears to be working correctly on the provided reproduction now.
If there are still existing issues with the cache behavior here other than the above could additional details be provided and we can investigate further?
Hi, @ijjk . Unfortunately the issue still exists. Just checked with a new deployments with the latest canary. Quick reminder, you must check the repo right after a fresh redeployment. A dedicated API is provided to redeploy the reproduction with deployment hooks under /control-panel -> "submit and redeploy" Here is what i do after redeployment to reproduce the issue:
https://github.com/vercel/next.js/assets/52538597/b0cd02d6-921f-4f8d-8b9a-ba5a1b4859e8
@Javad9s Thank you for putting together such a thorough test. I think the problem keeps getting overlooked because it is so intermittent.
@leerob I've spent literal days off and on over the past 4-6 months trying to get this to work. On new deployments there is almost always an issue with revalidation with static pages and generateStaticParams pages. Then after testing 3-4 times it starts to feel like it's working (as if it needs to warm up or something), but the more you test you can still find cases of stale data that won't update without another revalidation.
I also noticed it appears to be a little more reliable on a paid plan, but still not 100% reliable (and I'd be happy with 99%). Is there a priority thing going on with updates getting lost? Without the ability of revalidatePath/Tag returning a success or error object we can't show you logs of it failing.
I want to get this to work because it feels like this is so much more efficient, and it's been advertised for years now. Idk if anyone can show a more comprehensive test for the Nextjs team to see what we're seeing.
Hi, thanks again for the thorough repro, we have identified an issue with the fresh deployment case and are working on a fix. We will update here once it has been rolled/is available!
Hi, final update here the fixes around this have been fully rolled out and are available now please re-deploy and give it a try!
Thanks again for providing such a robust reproduction to help track this down!
Thank you. Definitely there has been some fixes, but I don't think the issue should be closed yet.
This is overall acceptable when we include any revalidate
time in cache functions: (unstable_cache_isr
or fetch_isr
)
unstable_cache(
async () => {
const randomNumber = GetRandomNumber();
return randomNumber;
},
[CACHED_NUMBER_TAG],
{ revalidate: 259200, tags: [CACHED_NUMBER_TAG] },
);
fetch(publicURL + "/api/get-number", { revalidate: 259200, tags: [CACHED_NUMBER_TAG] });
Although there is one weird behavior similar to stale-while-revalidate for pages with prefetch=false
only before first MPA reload.
In original repo, Link
to static/04 is generated with prefetch=false
.
But if cache function doesn't include a revalidate
time: (unstable_cache
or fetch
)
unstable_cache(
async () => {
const randomNumber = GetRandomNumber();
return randomNumber;
},
[CACHED_NUMBER_TAG],
{ tags: [CACHED_NUMBER_TAG] },
);
fetch(publicURL + "/api/get-number", {tags: [CACHED_NUMBER_TAG], cache: "force-cache"});
For first revalidation MPA navigation returns the new data, but SPA navigations (Link
or router.refresh()
) still return stale data. Also with every next revalidation nothing new happens and it seems it is stuck forever.
@Javad9s it sounds like for the client-navigation case and wanting to avoid stale data you'd want to leverage the new staleTime
config https://nextjs.org/docs/app/api-reference/next-config-js/staleTimes
@Javad9s it sounds like for the client-navigation case and wanting to avoid stale data you'd want to leverage the new
staleTime
config https://nextjs.org/docs/app/api-reference/next-config-js/staleTimes
I'm aware of that. But pretty sure i'm seeing a bug in here.
Reproduction steps:
Is this now supposedly working as expected? I am having the following issue on 14.2.3:
I am using Strapi as a CMS with a webhook that calls /api/my-endpoint/route.ts. That route.ts is simple:
import { revalidateTag } from "next/cache";
export async function POST(request: Request) {
const body = await request.json();
const url = body.entry.url; // url would be something like /case-studies
revalidateTag(url);
return Response.json({ message: `Cache invalidated for ${url}` });
}
I then have the following code that renders all pages for me, in a [...slug]/page.tsx file:
async function fetchContent(slug: string[]) {
const urlSlug = slug.join("/");
const response = await fetch(
`strapiserver`,
{
next: { tags: [urlSlug] }, // imagine /case-studies
}
);
...
return await response.json();
}
export async function generateStaticParams() {
const res = await fetch(`strapiendpoint`);
const pages = await res.json();
const params = pages.data
.map((page: any) => {
return {
slug: page.attributes.url.split("/").filter(Boolean),
};
})
.filter((param: any) => param.slug.length > 0);
return params;
}
export default async function Page({ params }: PageProps) {
...
}
I can see that when my webhook fires (or a manual post happens thru postman), that my api endpoint is running and returning 200. However, the cache is not being invalidated.
I tried a few inputs from the thread, adding this to my [...slug]/pages.tsx but it had no effect.
export const dynamic = "auto",
dynamicParams = true;
I am not sure if I am missing something with my approach though, the content is only rebuilt on deployment. Here is a screenshot of my build output.
I moved my tag from something containing a forward slash to just be text and it appears to work.
I too am having this problem on 14.2.3.
Same pattern with calling revalidateTag in an api route. It does invalidate but it shows the previous change. So If I change something in Sanity from 'foo' to 'bar' and publish, nothing changes. But then if I change 'bar' to 'baz' and publish then I see 'bar' on the site. If I then change 'baz' in the CMS to 'rar' then I can see 'baz' in the live site.
The change in question is happening in a navbar component
That is nested inside of statically generated routes like the home page in this example
Hi, the above mentioned issues have been investigated and rolled out/validated here https://nextjs-revalidation-test-p57ow3odr-vtest314-ijjk-testing.vercel.app/static/01 please re-deploy your project and test it out!
Link to the code that reproduces this issue
https://github.com/Javad9s/nextjs-revalidation-test
https://nextjs-revalidation-test.vercel.app/
To Reproduce
Deploy the project to Vercel and set this environment variables:
fetch
orfetch_isr
orfetch_no_force
orunstable_cache
orunstable_cache_isr
true
orfalse
Special logs that are generated by RENDER_LOG are formatted like this: "### --- HH:mm:ss --- Log Text" and can be found in vercel dashboard.
If you see "Global Cache: api-error" on website because the internal api was not ready during build, deploy the project again and it should be ok.
Current vs. Expected behavior
1 - Behavior with fetch and
cache: "force-cache"
(CACHE_METHOD = "fetch"):Go to dynamic page (which will render in each hit). You should see something like "Global Cache: <266> 12-07 07:46:03". This value is what we expect to see in all other pages [1].
Go to Control Panel. Then click on
revalidatePath("/", "layout")
[2].Go to dynamic page again. You will see new global cache in dynamic page. You should see some logs like this in dashboard as well: "### --- 08:24:58 --- Called get-number api" and "### --- 08:26:09 --- Rendered dynamic page.tsx"
Go to other static pages and param pages. Notice pages that were previously cached during build process, have a hard time revalidating and you won't see a log as well. Hence "/params/01" and "/params/02" will still show old data because they are rendered using
generateStaticParams()
. but other params (e.g. /params/03) will render again and show fresh data.In this stage if you somehow can cause a new render in those pages, they will revalidate and cache properly from this point forward (in another word they are cleaned). The workaround is you go to that page and hit reloads (ctrl + R). Keep in mind soft navigation and
router.refresh()
won't cause a new render in this stage. If you are lucky enough, you can get one or two new renders in every step, then you click onrevalidatePath("/", "layout")
again and repeat the process until you clean all of the pages [3].2 - Behavior with isr fetch (CACHE_METHOD = "fetch_isr"):
Same as 1.1
Same as 1.2
Same as 1.3
Most pages will render again properly here.
If a page is still serving old data, one reload (ctrl + R) will cause a new render, but keep in mind you will still see the stale page until next reload or soft navigation or
router.refresh()
[3].For isr pages that have
prefetch = false
including "isr 10s" and "isr 2h", first time navigating will cause a new render but new data will always be served in next visit [3].Verify canary release
Provide environment information
Which area(s) are affected? (Select all that apply)
Not sure
Additional context
Side issues:
[1] Cache is not consistence between build on vercel and dynamic page
At first deploy, global cache is different between static pages and dynamic page. They serve a new and updated global cache while dynamic page is serving the one from previous build.
[2] Calling revalidatePath in a server action causes unnecessary render on the current page
This happens in local build as well. Control panel will render once, which will be lost and will not be cached. Next time you visit control panel you might still get old data or a different set of data. For this issue in local build, you can call revalidatePath(custom) and keep an eye on different values under "Page Specific" section in control panel (also keep in mind react, renders each page two times, one for hard reload and one for RSC and soft navigation).
[3] On Vercel: App router serves stale data despite rendering fresh pages
When attempting to revalidate with hard reloads. If you are lucky and caused a new render, at that specific hit you still get the stale data while you see the render log in the dashboard. Only After next reload or soft navigation or
router.refresh()
new rendered page will be served. This behavior is extremely intense in "isr 10s" page.