Caching issue with Next.js App Router - Vercel Deployment

Dear Prismic team

I set up a new Next.js App Router project using your setup command npx @slicemachine/init@latest and walking trough your step by step setup guide.

In previous versions, I never had issues deploying the site to Vercel and setting up Prismic Webhooks to trigger redeploys.

With this new project it seems like there are some caching issues with Vercel:
If I push a new commit to Github or if I edit content on Prismic, it triggers a new deploy correctly.
Unfortunately those deploys are missing the newest contents from Prismic and every then and now it appears the following error:

ForbiddenError: Access to this Ref requires an access token
    at Client.fetch (/vercel/path0/.next/server/chunks/734.js:2367:27)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Client.get (/vercel/path0/.next/server/chunks/734.js:1450:16)
    at async Client.dangerouslyGetAll (/vercel/path0/.next/server/chunks/734.js:1515:28)
    at async Client.getAllByType (/vercel/path0/.next/server/chunks/734.js:1767:16)
    at async Object.generateStaticParams (/vercel/path0/.next/server/app/portfolio/[portfolio]/[uid]/page.js:536:19)
    at async buildParams (/vercel/path0/node_modules/next/dist/build/utils.js:917:36)
    at async /vercel/path0/node_modules/next/dist/build/utils.js:934:33
    at async /vercel/path0/node_modules/next/dist/build/utils.js:1067:117
    at async Span.traceAsyncFn (/vercel/path0/node_modules/next/dist/trace/trace.js:103:20) {
  url: 'https://my-repo.cdn.prismic.io/api/v2/documents/search?q=%5B%5Bat%28document.type%2C+%22project%22%29%5D%5D&pageSize=100&ref=ZLphbxEAACMAGdpk&routes=%5B%7B%22type%22%3A%22page%22%2C%22uid%22%3A%22home%22%2C%22path%22%3A%22%2F%22%7D%2C%7B%22type%22%3A%22page%22%2C%22path%22%3A%22%2F%3Auid%22%7D%2C%7B%22type%22%3A%22portfolio%22%2C%22path%22%3A%22%2Fportfolio%2F%3Auid%22%7D%2C%7B%22type%22%3A%22project%22%2C%22resolvers%22%3A%7B%22portfolio%22%3A%22portfolio%22%7D%2C%22path%22%3A%22%2Fportfolio%2F%3Aportfolio%2F%3Auid%22%7D%5D',
  response: {
    type: 'api_security_error',
    message: 'Access to this Ref requires an access token',
    oauth_initiate: 'https://my-repo.prismic.io/auth',
    oauth_token: 'https://my-repo.prismic.io/auth/token'
  }
}

In both cases I have to redeploy the site manually and force Vercel to not use the cache. If I do so, everything works fine.

Do you have any idea of how I can fix this?

In my prismicio.ts file I have the following recommended code which contains some lines about caching:

export const createClient = (config: prismicNext.CreateClientConfig = {}) => {
  const client = prismic.createClient(repositoryName, {
    routes,
    fetchOptions:
      process.env.NODE_ENV === 'production'
        ? { next: { tags: ['prismic'] }, cache: 'force-cache' }
        : { next: { revalidate: 5 } },
    ...config,
  });

  prismicNext.enableAutoPreviews({
    client,
    previewData: config.previewData,
    req: config.req,
  });

  return client;
};

Thanks for your support.

Which version of Next are you using, a fix for a similar error was release a while ago: fix: use .mjs module exports by angeloashmore · Pull Request #111 · prismicio/prismic-react · GitHub

I use the following versions of probably relevant packages:

  • Next 13.4.12
  • @prismicio/next 1.3.3
  • @prismicio/client 7.1.0
  • @slicemachine/adapter-next 0.3.9
  • slice-machine-ui 1.7.1

And I use the new src directory of Next.js.

I ran into the same issue. Adding an access token solved it. More info on generating one can be found here: Access Token - Documentation - Prismic

  const client = prismic.createClient(repositoryName, {
    routes,
    accessToken: process.env.PRISMIC_ACCESS_TOKEN,
    fetchOptions:
      process.env.NODE_ENV === "production"
        ? { next: { tags: ["prismic"] }, cache: "force-cache" }
        : { next: { revalidate: 5 } },
    ...config,
  });

In your .env.local and on Vercel add:
PRISMIC_ACCESS_TOKEN=YOUR_TOKEN

1 Like

Thanks for your answer.
Does this solve the content caching issue as well?

I was also having caching issues but realized that was my fault. I had set dynamicParams to false. Which I had done in my page.tsx:

export const dynamicParams = false;

Removing it solved that issue for me. You can read more about dynamicParams here: File Conventions: Route Segment Config | Next.js

I also use export const dynamicParams = false; in my page files.
But I guess, this makes sense as my pages only update when there is an update in the Prismic Repo - and if this is the case, it triggers a redeploy with a webhook.

If I understand it correctly, the dynamicParams setting only impacts routes and not content on those pages, and currently I have the issue that new routes and new contents (like a list of entities of a custom type) are missing out of builds.

dynamicParams = false is also included in the Page Snippet (in Slicemachine), so I guess this complies with the core Prismic concept?

Any idea on what the problem could be, @Pau or @angeloashmore?

I'm having the same issue here. I did the security token recommendation by @nathan and I don't understand what's going on.
I was seeing that issue and then changed the API access option to "open" and I was able to deploy successfully, however, if I make changes inside the primic interface such as changing text, it is not showing in my website as if I had a special cache configuration

1 Like

I reconfigured the webhook from vercel to prismic and it is now working as expected. So I guess that adding the accessToken and re-doing the webhook solved my problem. I hope that this can help you guys

1 Like

I've gone down a similar rabbit hole here, and found a decent solution with Vercel.

The new prismic/next/isr fetch() cache setup was working great; updates in Prismic were invalidaiting the Vercel correctly via the /api/revalidate call.

However, at build time I was getting "repo not found" errors from the prismic API. The build routine was trying to query an old cached master ref.

I found that because Vercel stores the whole .next build directory between builds, Next was using fetch responses from the previous build under ./next/cache/fetch-cache.

Nuke that directory before each build, and the latest Prismic master will be used. No need to mess with createClient() setup.

"scripts": {
    "build": "rm -rf .next/cache/fetch-cache && next build",
},

I hope this helps somebody out there! - Kyle

6 Likes

This was helpful. We had a similar situation. When there is multiple [:uid]/page.js files, e.g. /[:uid]/page.js and /some-path/[:uid]/page.js

It seems like subsequent createClient() calls trigger a not-found repo error. There very well be some kind of fetch cache on createClient() or client.getAllByType(...).

After adding Kyle's suggestion:

  • client.getByType('page')
  • client.getAllByType('page')
  • as well as creating a static array of uid's

All work as expected within generateStaticParams()

1 Like

Another option is to use the Environment Variable VERCEL_FORCE_NO_BUILD_CACHE with a value of 1. You can find limited info on that here. This has solved the issue for me on multiple projects.

Edit: After another day of dev the error RefExpiredError: The provided ref is no longer accessible, it has expired. has popped back up using the VERCEL_FORCE_NO_BUILD_CACHE option shared above. I'm going to give @kyle's suggestion a shoot, hopefully with better luck.

1 Like

Perhaps it would be helpful, if you could extend the Next.js / Deploy documentation with the most proven deployment methods (in addition to the blog post).
Especially for those who are new to Prismic and the App Router, it might be difficult to find the best way to deploy the projects.

I now use on-demand revalidation with a webook to /api/revalidate to reflect quick changes, but still trigger a rebuild of the application to rebuild my sitemap (app/sitemap.js) too.
If anyone has a better approach to that, please let me know. :slightly_smiling_face:

1 Like

It probably stems from the changes in fetch with next.js 13.x and the app router. All fetch requests get cached by default (it think).

Is there a specific strategy that Prismic has found helpful with their latest site release and updates now that their main site is Next.js? Maybe Prismic can chime in ;)

Hey @ryan,

You're absolutely correct that we rebuilt our main site with the Next.js App Router recently, but we're in the same boat as everyone else. We're trying to debug the issue with caching, but we haven't figured it out yet. We'll update this thread as soon as we have a solution or a temporary workaround.

Sam

2 Likes

Hey everyone,

We've opened an issue on the Next.js GitHub repository. Please feel free to upvote this issue and follow along for updates:

Sam

2 Likes

I am about to pass off the project to a client. Is there a reliable way to ensure their updates in Prismic get reflected on the frontend?

I am getting wildly inconsistent results with the revalidateTag webhook. Should I also trigger a build on the Vercel side after the revalidate endpoint is called?

Please help! and Thank you

Edit: I would like to add my changes (in even in Production) are reflected in Draft/Preview mode but not on the live site (after publishing).

1 Like

Hi @cires2023,

I'm not familiar with all of the rendering methods in Next 13, but maybe you could consider doing a full-site rebuild instead of ISR? It's not ideal, but I imagine it might be more fool-proof until these issues get ironed out.

Sam

I'm now also facing caching issues on Vercel in Next.js applications (v14.0.3) using the pages router.
Editing content in Prismic triggers a complete rebuild but the new contents are missing.

This also happens with the following suggested option: