Search code examples
cachingnext.jsvercelsanity

Bust cache after content change with Sanity?


I'm using Sanity as a CMS and Next JS as my frontend. I’d like my site to be able to handle a reasonable amount of traffic so I think I need some caching.

However if an editor makes a change to the content in Sanity and then refreshes the live site they will expect to see the change right away. Is there a way to achieve both?

Below is my Next JS component. I had to add force-dynamic to prevent the page from being statically generated, otherwise the content doesn't update until re-deployed.

I also had to set useCdn: false for editors to see their changes immediately, however according to the docs this makes the API calls slower and more expensive: https://www.sanity.io/help/js-client-cdn-configuration

import { createClient } from "next-sanity";

const client = createClient({
  projectId: 'process.env.NEXT_PUBLIC_SANITY_PROJECT_ID',
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
  apiVersion: process.env.NEXT_PUBLIC_SANITY_API_V,
  useCdn: false,
});

export default async function Home() {
  const res = await client.fetch(
    `*[_type == "posts"] {
    _id,
    name
  }`,
  );
  return (
    <div>
      {JSON.stringify(res, null, 2)}
    </div>
  );
}

export const dynamic = "force-dynamic";

Solution

  • Not sure if this is a good solution but it does seem to work.

    Set a cookie when a user logs in to identify them as an Editor: document.cookie = "sanityRole=Editor; path=/";

    Then check for the cookie and don't use the CDN if its detected.

    One downside is if the editor makes a change on one browser or device but looks on another without also logging in then they'll still hit the CDN.

    An even better solution would be to bust the cache when the content changes so that all users see the latest data, but not sure if thats possible.

    import { cookies } from "next/headers";
    import { createClient } from "next-sanity";
    
    export default async function Home() {
    
      const userIsEditor: boolean =
        cookies()
          .getAll()
          .find((c) => c.name === "sanityRole")?.value === "Editor";
      
      const client = createClient({
        projectId: 'process.env.NEXT_PUBLIC_SANITY_PROJECT_ID',
        dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
        apiVersion: process.env.NEXT_PUBLIC_SANITY_API_V,
        useCdn: !userIsEditor,
      });
    
      const res = await client.fetch(
        `*[_type == "posts"] {
          _id,
          name
        }`,
      );
    
      return (
        <div>
          {JSON.stringify(res, null, 2)}
        </div>
      );
    }
    
    export const dynamic = "force-dynamic";