You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js中Apollo Client拒绝更新缓存,求彻底禁用缓存方案

在Next.js 14.2.5 SSR环境中彻底禁用Apollo Client缓存,强制每次获取最新数据

我们在Next.js 14.2.5的SSR环境中使用Apollo Client,通过getClient初始化客户端,但无论怎么配置,Apollo Client都不会用服务器返回的最新数据更新缓存。已经用Postman验证API返回的是最新数据,但查询始终返回旧数据。尝试过设置fetch-policy为no-cache、修改defaultOptions禁用缓存、切换客户端、禁用Next.js缓存,都没效果。需求是每次页面加载都从API获取最新数据,彻底禁用任何缓存机制。


现有相关代码

Apollo客户端配置

import { HttpLink } from "@apollo/client";
import {
  registerApolloClient,
  ApolloClient,
  InMemoryCache,
} from "@apollo/experimental-nextjs-app-support";

export const { getClient } = registerApolloClient(() => {
  return new ApolloClient({
    link: new HttpLink({
      uri: `${process.env.NEXT_PUBLIC_ADMIN_BASE_URI}/api/graphql`,
    }),
    defaultOptions: {
      query: {
        fetchPolicy: "network-only",
      },
    },
    ssrMode: true,
    ssrForceFetchDelay: 1,
    cache: new InMemoryCache({
      resultCaching: false,
      typePolicies: {
        Yachts: {
          merge: true,
          fields: {
            keyFeatures: {
              merge(existing = [], incoming: any[], { readField }) {
                const merged: any[] = existing ? existing.slice(0) : [];
                const featureNameToIndex: Record<string, number> = {};

                existing.forEach((feature: any, index: any) => {
                  const name = readField<string>("name", feature);
                  if (name) {
                    featureNameToIndex[name] = index;
                  }
                });

                incoming.forEach((feature) => {
                  const name = readField<string>("name", feature);
                  if (name) {
                    const index = featureNameToIndex[name];
                    if (typeof index === "number") {
                      merged[index] = {
                        ...merged[index],
                        ...feature,
                      };
                    } else {
                      featureNameToIndex[name] = merged.length;
                      merged.push(feature);
                    }
                  }
                });

                return merged;
              },
            },
          },
        },
      },
    }),
    /*defaultOptions: {
      watchQuery: {
        fetchPolicy: "no-cache",
        errorPolicy: "ignore",
      },
      query: {
        fetchPolicy: "no-cache",
        errorPolicy: "all",
      },
      mutate: {
        fetchPolicy: "no-cache",
      },
    },*/
  });
});

服务端查询函数

"use server";

import IBrokerino from "@/types/brokerino";
import { getClient } from "@/apollo";
import { gql } from "@apollo/client";

export const fetchBrokerinos = async (): Promise<IBrokerino[]> => {
  const client = getClient();
  const { data } = await client.query({
    query: gql`
      query Users {
        Users(where: { displayOnWebsite: { equals: true } }) {
          docs {
            name
            picture {
              alt
              sizes {
                fhd {
                  url
                  width
                  height
                }
              }
            }
            phones {
              prefix
              number
            }
            langs
            email
            position
          }
        }
      }
    `,
  });
  return data.Users.docs;
};

Page组件调用方式

import Hero from "@/components/company/hero";
import Bar from "@/components/nav/bar";
import dynamic from "next/dynamic";
import { fetchBrokerinos } from "@/actions/brokerino";

const View = dynamic(() => import("@/components/view"));
const Footer = dynamic(() => import("@/components/footer"));
const Story = dynamic(() => import("@/components/company/story"));
const Accordion = dynamic(() => import("@/components/company/accordion"));
const Team = dynamic(() => import("@/components/company/team"));
const Lifestyle = dynamic(() => import("@/components/company/lifestyle"));

const Company = async () => {
  return (
    <main className="w-full flex flex-col justify-start items-center">
      <Bar dynamicColor={-1} />
      <View />
      <Hero />
      <Story />
      <Accordion />
      <Team brokerinos={await fetchBrokerinos()} />
      <Lifestyle />
      <Footer />
    </main>
  );
};

export default Company;

彻底禁用缓存的解决方案

1. 单个查询强制禁用缓存

在查询函数中明确指定fetchPolicy和nextFetchPolicy,确保该查询完全绕过缓存:

export const fetchBrokerinos = async (): Promise<IBrokerino[]> => {
  const client = getClient();
  const { data } = await client.query({
    query: gql`...`, // 保留原查询语句
    fetchPolicy: "no-cache", // 不从缓存读取,也不写入缓存
    nextFetchPolicy: "no-cache", // 后续重复查询也遵循该策略
  });
  return data.Users.docs;
};

2. 全局配置Apollo客户端禁用缓存

修改客户端初始化代码,关闭所有缓存相关机制:

export const { getClient } = registerApolloClient(() => {
  return new ApolloClient({
    link: new HttpLink({
      uri: `${process.env.NEXT_PUBLIC_ADMIN_BASE_URI}/api/graphql`,
      // 禁用HTTP层面的缓存
      fetchOptions: {
        cache: "no-store",
      },
    }),
    defaultOptions: {
      watchQuery: {
        fetchPolicy: "no-cache",
        errorPolicy: "all",
      },
      query: {
        fetchPolicy: "no-cache",
        errorPolicy: "all",
        nextFetchPolicy: "no-cache",
      },
      mutate: {
        fetchPolicy: "no-cache",
      },
    },
    ssrMode: true,
    // 清空缓存规则,关闭结果缓存
    cache: new InMemoryCache({
      resultCaching: false,
      typePolicies: {},
    }),
  });
});

极端情况:可以直接导入NoCache替代InMemoryCache,彻底移除缓存层。

3. 禁用Next.js服务端组件缓存

在Page组件顶部添加revalidate: 0,强制Next.js每次请求都重新渲染页面:

export const revalidate = 0; // 每次请求都重新生成页面

const Company = async () => {
  // 保留原组件代码
};

export default Company;

或者在服务端查询函数中使用noStore禁用函数级缓存:

"use server";

import { unstable_noStore as noStore } from "next/cache";
// 其他导入语句

export const fetchBrokerinos = async (): Promise<IBrokerino[]> => {
  noStore(); // 禁用该函数的缓存
  const client = getClient();
  const { data } = await client.query({
    query: gql`...`,
    fetchPolicy: "no-cache",
  });
  return data.Users.docs;
};

4. 验证请求是否触发

在HttpLink中添加日志,确认每次页面加载都发起了新请求:

link: new HttpLink({
  uri: `${process.env.NEXT_PUBLIC_ADMIN_BASE_URI}/api/graphql`,
  fetchOptions: { cache: "no-store" },
  fetch: async (uri, options) => {
    console.log("发起GraphQL请求:", uri);
    return fetch(uri, options);
  },
}),

内容的提问来源于stack exchange,提问作者Gregory Buffard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:51:00