Next.js Discord

Discord Forum

Sanity + app router + revalidateTag() is unpredictable

Answered
Jersey Wooly posted this in #help-forum
Open in Discord
Jersey WoolyOP
I try to get next app router + revalidateTag() work with Sanity but it’s either completely unpredictable or I totally misunderstood something.

I now spent 5 full days trying to make it work and build multiple projects, so asking is my last hope. lol. Here’s what I can tell now:

Project #1: This is the most basic, simple setup (posts, pages, categories, [slug] dynamic pages). I think this works. https://github.com/thedevdavid/sanity-revalidate-debug

Project #2: Almost the same setup (posts, pages, categories, [slug] dynamic pages + subpages with extra tags). https://github.com/thedevdavid/productengineerjobs/blob/develop/app/(site)/post-a-job/page.tsx
Here, the simple [job] or [benefit] requests are never getting revalidated on the / and /post-a-job routes. But in for example /contract/[slug] route. And the complex tags, like [job:${params.slug}] or [page:${params.slug}] are all working well.

Project #3 & #4: Very similar to project #2. posts, pages, categories + extra schema types, like team members, nav links, etc. Here I can’t even tell the exact problems. Probably similar to project #2 but I’m not sure anymore. Although there’s 1 thing I know that’s extra. There’s a homepage type with the fetch tag, homepage . This holds the navigation links. There’s a fetch tagged homepage on (site)/page.tsx and in 2 components (Navbar & Footer). Both rended from (site)/page.tsx. The fetch in the components gets revalidated. I can see the new data on all pages, excet the / route. That route ever gets revalidated. Although the page and 2 components inside have tagged requests.

In all 4 projects, the Sanity webhook calls the revalidate API route. The function always succeeds. Params are what they are supposed to be, so I guess the revalidateTag() gets called with the right parameters. (Tho I did not figure out how to debug the actual function calls yet)

Soooo I feel totally lost and I haven’t even tried to include previews and draft mode yet.
Answered by Jersey Wooly
Closing this.
If anyone else struggling with this: it looks like the next.js cache/vercel cache is absolutely unpredictable right now. Went ahead to investigate with the Sanity team but they also pointed to Next.js at the end, as well as many other github issues in the past weeks.
View full answer

7 Replies

Jersey WoolyOP
Example fetch call (fails to revalidate, on / route):
  const jobs = await sanityFetch<Job[]>({
    query: jobsQuery,
    tags: ['job'],
  });


Example fetch call (revalidates. /[slug] route):
const page = await sanityFetch<Page>({
    query: pagesBySlugQuery,
    params: { slug: params.slug },
    tags: [`page:${params.slug}`],
  });
  


sanityFetch function:
export async function sanityFetch<QueryResponse>({
  query,
  params = DEFAULT_PARAMS,
  tags = DEFAULT_TAGS,
}: {
  query: string;
  params?: QueryParams;
  tags: string[];
}): Promise<QueryResponse> {
  return client.fetch<QueryResponse>(query, params, {
    // We only cache if there's a revalidation webhook setup
    cache: revalidateSecret ? "force-cache" : "no-store",
    next: {
      //revalidate: 30, // for simple, time-based revalidation
      tags, // for tag-based revalidation
    },
  });
}


Revalidate route handler:
import { revalidateTag } from "next/cache";
import { NextResponse, type NextRequest } from "next/server";
import { parseBody } from "next-sanity/webhook";

import { revalidateSecret } from "@/lib/sanity.api";

export async function POST(req: NextRequest) {
  try {
    const { body, isValidSignature } = await parseBody<{
      _type: string;
      slug?: string | undefined;
    }>(req, revalidateSecret);
    if (!isValidSignature) {
      const message = "Invalid signature";
      return new Response(message, { status: 401 });
    }

    if (!body?._type) {
      return new Response("Bad Request", { status: 400 });
    }

    revalidateTag(body._type);
    if (body.slug) {
      revalidateTag(`${body._type}:${body.slug}`);
    }
    return NextResponse.json({
      status: 200,
      revalidated: true,
      now: Date.now(),
      body,
    });
  } catch (err: any) {
    console.error(err);
    return new Response(err.message, { status: 500 });
  }
}
Jersey WoolyOP
Might worth noting: when revalidate works somewhere, it usually only works if I refresh cmd+shift+R, not simply cmd+R.
Jersey WoolyOP
fyi: problem still exists on 13.5.3
Jersey WoolyOP
update: looks like I'm not the only one struggling with this https://github.com/vercel/next.js/issues/55960
Jersey WoolyOP
Closing this.
If anyone else struggling with this: it looks like the next.js cache/vercel cache is absolutely unpredictable right now. Went ahead to investigate with the Sanity team but they also pointed to Next.js at the end, as well as many other github issues in the past weeks.
Answer
Ojos Azules
Kinda late but did you manage to fix this? It's driving me insane
American Crocodile
This is not a fix but a tip, the Sanity slack is very helpful and has devs from Sanity answering in it
https://slack.sanity.io/