我们在 Web 应用程序中使用 apollo 客户端,并正在寻找提高缓存使用率的方法。
我们有一个以 id 数组作为参数的查询,一个带有 id foo
的示例查询和 bar
看起来像这样:
query routes {
routes(routeNames: ["foo", "bar"]) {
items {
name
route
defaults
}
}
}
缓存设置如下所示:
export const cacheRedirects = {
Query: {
routes: (_: any, args: RoutesArgs, { getCacheKey }: Resolver<'name'>): Array<CacheKey> =>
args.routeNames.map(name => getCacheKey({ __typename: 'Route', name })),
},
};
export const dataIdFromObject = (object: QueryResult): ?string => {
switch (object.__typename) {
case 'Route':
return `${object.__typename}:${object.name}`;
default: return defaultDataIdFromObject(object);
}
};
export function newCache(): InMemoryCache {
return new InMemoryCache({ dataIdFromObject, cacheRedirects });
}
现在,当在客户端的多个位置使用查询时,我们希望仅获取未通过网络缓存的 routeNames 的数据,并通过缓存检索其余数据。
所以问题归结为:
当有一个查询缓存
routeNames: ["foo", "bar"]
的结果时稍后出现另一个查询,询问 routeNames: ["bar", "baz"]
的路线我们希望得到与 "bar"
对应的结果从缓存中发送查询 routeNames: ["baz"]
.我不确定 Apollo 是否以及如何做到这一点,因为与 cacheRedirect example 相比在这里,我们处理多个 id 而不是一个。
现在,如果我们不能缓存每个数组项,我们可以做的下一个最好的事情是将 id 转换为公共(public)缓存键,以便
["foo", "bar"]
和 ["bar", "foo"]
最终使用相同的缓存键,但 ["foo", "baz"]
会使用不同的。当然,理想的做法是只获取
"baz"
作为我们场景中缺少的项目。
最佳答案
一种想法是在进行实际查询之前检查本地缓存,并简单地将缓存中已经存在的 ID (routeNames) 从 ID (routeNames) 列表中删除以进行查询。
要在不接触网络的情况下检查缓存,请使用 readQuery()
或 readFragment()
.
文档在这里:
https://www.apollographql.com/docs/react/advanced/caching.html#readquery
https://www.apollographql.com/docs/react/advanced/caching.html#readfragment
更新:或者您也可以设置 fetchPolicy
至cache-only
在您的查询选项中。
https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-config-options-fetchPolicy
更新 2:集成检查以便它们为每个查询运行的一种好方法可能是自定义客户端中间件,该中间件将在调用服务器之前在每个请求上运行。
https://www.apollographql.com/docs/react/advanced/network-layer.html#linkMiddleware
关于caching - 使用 Apollo 缓存具有多个 id 的 GraphQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51637618/