Next.js生产环境SSR下Apollo Client GraphQL查询不触发问题求助
排查思路
- 优先确认Next.js API路由缓存规则:Next.js生产环境对GET类型的API路由默认开启静态缓存,和你是否配置Apollo的maxAge无关,这是开发和生产环境行为不一致的核心诱因
- 排查Apollo Client实例复用逻辑:SSR场景下如果全局复用同一个Apollo Client实例,会导致内存缓存跨请求生效,开发环境热重载会销毁实例所以不会触发该问题
- 验证Next.js全局fetch缓存规则:Next 13及以上版本全局fetch默认强制缓存,所有未显式声明缓存策略的请求都会被持久化缓存
可落地解决方案
1. 强制API路由不缓存
在/api/graphql.js文件头部添加以下配置,同时修改响应头:
// 禁用页面级缓存 export const revalidate = 0; export default async function handler(req, res) { // 强制响应不缓存 res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); res.setHeader('Surrogate-Control', 'no-store'); // 原有转发逻辑不变 }
2. 调整Apollo Client默认查询策略
在/apollo/client.js初始化时,显式指定全局默认fetch策略,同时给fetch方法添加Next.js专属的无缓存配置:
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; const httpLink = createHttpLink({ uri: '/api/graphql', // 强制fetch不缓存 fetchOptions: { cache: 'no-store', }, }); export function createApolloClient() { return new ApolloClient({ ssrMode: typeof window === 'undefined', link: httpLink, cache: new InMemoryCache(), // 全局默认查询策略走网络请求,不使用本地缓存 defaultOptions: { watchQuery: { fetchPolicy: 'network-only', nextFetchPolicy: 'network-only', }, query: { fetchPolicy: 'network-only', }, }, }); }
3. 确保SSR场景下每次请求都创建新的Apollo Client实例
不要全局单例导出Apollo Client,每次SSR请求调用createApolloClient()生成新实例,避免跨请求的内存缓存复用:
// 正确用法:每个SSR请求初始化新实例 export async function getServerSideProps() { const client = createApolloClient(); const { data } = await client.query({ query: YOUR_QUERY }); return { props: { data } }; }
4. 临时兜底方案
如果以上配置仍未生效,可在每个GraphQL查询的变量里添加一个随机数参数,强制绕过所有层级的缓存:
query ComplaintList($random: Float!) { complaintConnection { edges { node { id content } } } }
查询时传入random: Math.random()即可,服务端可忽略该参数不做处理。
内容的提问来源于stack exchange,提问作者Zied Hamdi
相关产品推荐
相关产品推荐

