nuxt / nuxt

The Intuitive Vue Framework.
https://nuxt.com
MIT License
54.69k stars 5k forks source link

ISR mode on vercel, how to control cache on vercel? when some reqs 403, and i don't want vercel to cache it. #23659

Closed TangsWang closed 1 year ago

TangsWang commented 1 year ago

Environment

nuxt 3.7.0 ISR Vercel

Reproduction

nuxt 3.7.0 ISR Vercel

Describe the bug

ISR mode on vercel, how to control cache on vercel? when some reqs 403, and i don't want vercel to cache it.

i add server middlerware, some req was 403 filtered by UA.

but when the 403 req came first, the 403 response was cache by vercel.

then, normal req 403 yet. so i do not want to cache the 403 res, how to do it ?

Additional context

No response

Logs

No response

TangsWang commented 1 year ago

so, Is it possible to disable ISR (Incremental Static Regeneration) for a specific page based on its response status code at the programmatic level?

TangsWang commented 1 year ago

i found this about next and vercel: import { revalidatePath } from 'next/cache';

export async function GET(request: Request) { const { searchParams } = new URL(request.url); if (searchParams?.secret !== process.env.MY_SECRET_TOKEN) { return new Response(Invalid credentials, { status: 500, }); } revalidatePath('/blog-posts'); return new Response( { revalidated: true, now: Date.now(), }, { status: 200, }, ); }

how to do in the nuxt3.7?

danielroe commented 1 year ago

Coming soon in Nitro 2.7: https://github.com/unjs/nitro/pull/1723.

Closing as this isn't really something we can solve in Nuxt, but feel free to open feature request/enhancement upstream in https://github.com/unjs/nitro.

GioChocolateBro commented 8 months ago

@TangsWang I'm having the same problem.

export default defineNitroPlugin((nitroApp) => {
  let dontCacheResponse = false;

  nitroApp.hooks.hook('error', () => {
    dontCacheResponse = true;
  });

  nitroApp.hooks.hook('render:response', (response) => {
    if (dontCacheResponse) {
      response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate';
    }
  });

  nitroApp.hooks.hook('afterResponse', () => {
    dontCacheResponse = false;
  });
});

I made a plugin that wont cache errors. you can add an extra if statement and check the status code on the error variable if you only want this for 403.

I'm still having problems with Vercel not listening to headers and still caching the request. This is how it is supposed to work tho. Have a ticket open with the currently.

jony1993 commented 7 months ago

@GioChocolateBro Have you heard back from Vercel?

I'm currently exploring ways to bypass caching in specific scenarios. One such scenario arises when errors occur, and the other is when a user is authenticated.

GioChocolateBro commented 7 months ago

@jony1993 yes I did! It's not ideal but it works. Currently have this set up:

export default defineNitroPlugin((nitroApp) => {
  let dontCacheResponse = false;

  nitroApp.hooks.hook('error', () => {
    dontCacheResponse = true;
  });

  nitroApp.hooks.hook('render:response', (response) => {
    if (dontCacheResponse) {
      response.headers['Cache-Control'] = 's-maxage=1';
    }
  });

  nitroApp.hooks.hook('afterResponse', () => {
    dontCacheResponse = false;
  });
});

This will cache the page for 1 sec and won't revalidate it on the background. Currently it's not possible to NOT cache the response sadly.