Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request is being cached despite passing next: { revalidate: 0 } #64956

Closed
abhishekmardiya opened this issue Apr 24, 2024 · 4 comments
Closed
Labels
bug Issue was opened via the bug report template.

Comments

@abhishekmardiya
Copy link

abhishekmardiya commented Apr 24, 2024

Link to the code that reproduces this issue

https://github.com/abhishekmardiya/reproduction-app

To Reproduce

import "server-only";

interface OptionsType {
  method: string;
  headers: Record<string, string>;
  cacheControl?: {
    next?: { revalidate: number };
  };
}

export const blogFetcher = async (arg: {
  url: string;
  params?: any;
  noCache?: boolean;
  isIsr?: boolean;
}): Promise<{ res: Response; data: any }> => {
  const API_BASE_URL = process?.env?.BLOG_DOMAIN_BASE_URL;
  const API_KEY = process?.env?.BLOG_API_KEY;

  let finalUrl = arg?.url;
  if (arg?.params) {
    // Convert the queryParams object into a string of URL-encoded parameters
    const queryString = new URLSearchParams(arg?.params)?.toString();

    // Construct the full URL with the query parameters
    finalUrl = `${arg?.url}?${queryString}`;
  }

  const headers: Record<string, string> = {
    "api-key": API_KEY!,
  };

  let cacheControl;
  if (arg?.noCache) {
    cacheControl = { next: { revalidate: 0 } };
  }
  if (arg?.isIsr) {
    cacheControl = { next: { revalidate: 3600 } };
  }

  const options: OptionsType = {
    method: "GET",
    headers,
    cacheControl,
  };

  const res = await fetch(`${API_BASE_URL}/${finalUrl}`, options);
  const data = await res?.json();

  return { res, data };
};







API CALL

import "server-only";

import { blogFetcher } from "@/utils/fetch/blogFetcher";
import { Blog } from "@/interfaces/blog";

export const getBlogList = async (params?: {
  [key: string]: string | string[];
}): Promise<{ blogList: Blog[]; totalBlog: number }> => {
  try {
    const { res, data } = await blogFetcher({
      url: "posts",
      noCache: true,
      params,
    });

    if (res?.ok) {
      return {
        blogList: data,
        totalBlog: data?.length,
      };
    } else {
      console.error("getBlogList api try block err:", data?.message);
    }
  } catch (err: any) {
    console.error("getBlogList api catch block err:", err?.message);
  }

  return {
    blogList: [],
    totalBlog: 0,
  };
};

export const getSingleBlog = async (params: {
  [key: string]: string | string[];
}): Promise<{ blog: Blog | null }> => {
  try {
    const { res, data } = await blogFetcher({
      url: "posts",
      params,
      isIsr: true,
    });

    if (res?.ok) {
      return {
        blog: data?.length ? data[0] : null,
      };
    } else {
      console.error("getSingleBlog api try block err:", data?.message);
    }
  } catch (err: any) {
    console.error("getSingleBlog api catch block err:", err?.message);
  }

  return {
    blog: null,
  };
};



Current vs. Expected behavior

I have encountered an issue where the getBlogList() API is being cached even after passing next: { revalidate: 0 } in the OptionsType object.

To provide context, within my codebase, I am making two API calls: getBlogList() and getSingleBlog(). Despite explicitly setting next: { revalidate: 0 } in the OptionsType object for the getBlogList() API call, the response is still being cached.

I have two pages. One page displays a list of all blogs, and the other page shows the details of a single blog. I'm using getBlogList() to fetch the list of blogs for the blog list page, and getSingleBlog() to fetch the details for the detailed blog page.

whenever I add a new blog to my application, I have to manually purge out the cache from Vercel in order for the new blog to be visible to our users in blog list page.

Provide environment information

Operating System:
  Platform: win32
  Arch: x64
  Version: Windows 10 Pro
  Available memory (MB): 16068
  Available CPU cores: 8
Binaries:
  Node: 20.12.0
  npm: N/A
  Yarn: N/A
  pnpm: N/A
Relevant Packages:
  next: 14.2.2 // Latest available version is detected (14.2.2).
  eslint-config-next: 14.1.0
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Not sure

Which stage(s) are affected? (Select all that apply)

Vercel (Deployed)

Additional context

No response

@abhishekmardiya abhishekmardiya added the bug Issue was opened via the bug report template. label Apr 24, 2024
@abhishekmardiya abhishekmardiya changed the title Requests are being cached despite passing next: { revalidate: 0 } Request are being cached despite passing next: { revalidate: 0 } Apr 24, 2024
@abhishekmardiya abhishekmardiya changed the title Request are being cached despite passing next: { revalidate: 0 } Request is being cached despite passing next: { revalidate: 0 } Apr 24, 2024
@abhishekmardiya abhishekmardiya changed the title Request is being cached despite passing next: { revalidate: 0 } Request Is being cached despite passing next: { revalidate: 0 } Apr 24, 2024
@abhishekmardiya abhishekmardiya changed the title Request Is being cached despite passing next: { revalidate: 0 } Request is being cached despite passing next: { revalidate: 0 } Apr 24, 2024
@mdahiemstra
Copy link

We are also experiencing this, I have { next: { revalidate: 0 } } added to my fetch() requests but I still see fetch-cache being created with a very high revalidate value (31536000).

In my case the request is fetching a authorisation token from my auth provider, so I do not want that to be cached. This is giving allot of issues for our environment.

@abhishekmardiya
Copy link
Author

We are also experiencing this, I have { next: { revalidate: 0 } } added to my fetch() requests but I still see fetch-cache being created with a very high revalidate value (31536000).

In my case the request is fetching a authorisation token from my auth provider, so I do not want that to be cached. This is giving allot of issues for our environment.

I have fixed the issue by adding export const fetchCache = "force-no-store"; to page.tsx
Reference: https://vercel.com/docs/infrastructure/data-cache/manage-data-cache

However, I feel that the above solution is still a workaround and not a robust solution.

@mdahiemstra
Copy link

Yeah thats a workaround, could be a solution for some people but in our case we want to rely on the intended behaviour of the framework, and in this case its not working as documented.

@ijjk
Copy link
Member

ijjk commented May 1, 2024

@abhishekmardiya in your reproduction you aren't setting next: { revalidate: 0 } on the options correctly, it is being nested under a cacheControl field which is invalid https://github.com/abhishekmardiya/reproduction-app/blob/9b3d7a327d4cd5bbb5a6cc655e3d997e782d8cd4/server/fetch.ts#L44

We have numerous tests ensuring revalidate: 0 skips the cache which are passing so I'm gonna close this. Please respond with additional details if this is still an issue after correcting the mentioned issued.

@ijjk ijjk closed this as completed May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template.
Projects
None yet
Development

No branches or pull requests

3 participants