如何让Apollo Client在ssrMode为true时遵守network-only获取策略?
解决Apollo Client SSR中useSuspenseQuery的缓存与网络请求问题
1. 让服务器端useSuspenseQuery强制走网络或遵守fetchPolicy
针对ssrMode: true的场景
当设置ssrMode: true时,Apollo默认复用服务器端缓存导致后续请求直接读缓存。要强制走网络,可直接在useSuspenseQuery中显式指定策略:
const { data } = useSuspenseQuery(GET_DATA_QUERY, { fetchPolicy: 'network-only', ssr: true, // 确保查询在SSR阶段执行 });
该配置会跳过缓存强制从网络拉取数据,同时保留SSR阶段的执行逻辑。
针对省略ssrMode的场景
省略ssrMode时的 hydration 错误,根源是跨请求复用了服务器端缓存。解决的核心是为每个请求创建独立的Apollo Client实例,同时搭配指定fetchPolicy:
// 服务器端每个请求调用一次该函数创建Client function createApolloClient() { return new ApolloClient({ uri: 'YOUR_GRAPHQL_ENDPOINT', cache: new InMemoryCache(), // 不设置ssrMode,每个请求拥有独立缓存空间 }); } // 组件中使用 const { data } = useSuspenseQuery(GET_DATA_QUERY, { fetchPolicy: 'network-only', });
独立实例的缓存相互隔离,不会出现过期缓存复用导致的 hydration 不匹配问题。
2. 客户端修改数据后,确保服务器端后续请求走网络
客户端修改数据后,服务器端要避免返回旧缓存,关键是禁止跨请求复用Apollo Client实例:
- 坚持为每个HTTP请求创建全新的Client实例,每个实例的缓存都是初始状态,自然会从网络拉取最新数据。
- 若因特殊场景必须复用Client实例(不推荐),则需在每个请求处理前手动清理缓存:
// 清除指定查询的缓存条目 await apolloClient.cache.evict({ query: GET_DATA_QUERY }); await apolloClient.cache.gc(); // 清理失效缓存 // 或直接重置整个缓存 await apolloClient.cache.reset();
3. 是否需要手动清除缓存?
- 如果服务器端为每个请求创建独立Apollo Client,无需手动清除缓存,每个实例的缓存都是全新的,天然隔离旧数据。
- 如果必须复用Client实例,则必须在每个请求处理前手动清理缓存或重置特定查询的缓存条目,否则会出现旧数据复用问题。
内容的提问来源于stack exchange,提问作者Moritz Roessler
相关产品推荐
相关产品推荐

