为什么相同类型的多响应查询和单项查询之间没有 Apollo 缓存命中?
Why do I not have an Apollo cache-hit between a multi-response query and a single-item query for the same type?
我正在使用 @vue/apollo-composable
和 @graphql-codegen
开发一个 vue3 项目。
我的索引页执行搜索查询。该查询的每个结果在页面上都有一个磁贴。我期待缓存会回答磁贴查询,但它们总是错过。
在页面级别,我执行以下查询:
query getTokens($limit: Int!) {
tokens(limit: $limit) {
...tokenInfo
}
}
在我执行的 tile 组件内部:
query getToken($id: uuid!){
token(id: $id) {
...tokenInfo
}
}
片段看起来像这样:
fragment tokenInfo on token {
id
name
}
预期:缓存将处理 tile 组件内 100% 的查询。 (我希望避免将这些数据序列化到 vuex 的失败)。
现实:我收到 n+1 次后端调用。我尝试了一系列排列,包括摆脱片段。如果我发送带有 fetchPolicy: 'cache-only'
的 getToken
调用,则不会返回任何数据。
apollo 客户端配置非常基础:
const cache = new InMemoryCache();
const defaultClient = new ApolloClient({
uri: 'http://localhost:8080/v1/graphql',
cache: cache,
connectToDevTools: true,
});
const app = createApp(App)
.use(Store, StateKey)
.use(router)
.provide(DefaultApolloClient, defaultClient);
我还附上了我的 apollo 开发工具的屏幕截图。看来缓存实际上正在填充规范化数据:
如有任何帮助,我们将不胜感激! :)
由于@xadm 的评论以及我在 Vue discord 上收到的一些反馈,我已经解决了这个问题。真的,我的困惑归咎于我对这些工具中的许多都是陌生的。决定生活在边缘并成为 vue3 的早期采用者(我在很多方面都喜欢它)让我更容易对现在文档质量的差异感到困惑。
也就是说,这就是我的解决方案。
问题:实际问题是,按照配置,Apollo无法知道getTokens
和getToken
return相同类型 (token
).
解决方案:我发现解决这个问题的最低配置如下:
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
token(_, { args, toReference }) {
return toReference({
__typename: 'token',
id: args?.id,
});
},
},
},
},
});
但是,感觉……对我来说有点恶心。理想情况下,我希望看到一种方法,只需将 apollo 指向我的模式副本或模式自省,然后让它为我解决这个问题。如果有人知道更好的方法,请告诉我。
更好的(?)解决方案:在短期内,我认为这是一个更具可扩展性的解决方案:
type CacheRedirects = Record<string, FieldReadFunction>;
function generateCacheRedirects(types: string[]): CacheRedirects {
const redirects: CacheRedirects = {};
for (const type of types) {
redirects[type] = (_, { args, toReference }) => {
return toReference({
__typename: type,
id: args?.id,
});
};
}
return redirects;
}
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
...generateCacheRedirects(['token']),
},
},
},
});
如果有人对这些有什么改进,请加一个comment/solution! :)
我正在使用 @vue/apollo-composable
和 @graphql-codegen
开发一个 vue3 项目。
我的索引页执行搜索查询。该查询的每个结果在页面上都有一个磁贴。我期待缓存会回答磁贴查询,但它们总是错过。
在页面级别,我执行以下查询:
query getTokens($limit: Int!) {
tokens(limit: $limit) {
...tokenInfo
}
}
在我执行的 tile 组件内部:
query getToken($id: uuid!){
token(id: $id) {
...tokenInfo
}
}
片段看起来像这样:
fragment tokenInfo on token {
id
name
}
预期:缓存将处理 tile 组件内 100% 的查询。 (我希望避免将这些数据序列化到 vuex 的失败)。
现实:我收到 n+1 次后端调用。我尝试了一系列排列,包括摆脱片段。如果我发送带有 fetchPolicy: 'cache-only'
的 getToken
调用,则不会返回任何数据。
apollo 客户端配置非常基础:
const cache = new InMemoryCache();
const defaultClient = new ApolloClient({
uri: 'http://localhost:8080/v1/graphql',
cache: cache,
connectToDevTools: true,
});
const app = createApp(App)
.use(Store, StateKey)
.use(router)
.provide(DefaultApolloClient, defaultClient);
我还附上了我的 apollo 开发工具的屏幕截图。看来缓存实际上正在填充规范化数据:
如有任何帮助,我们将不胜感激! :)
由于@xadm 的评论以及我在 Vue discord 上收到的一些反馈,我已经解决了这个问题。真的,我的困惑归咎于我对这些工具中的许多都是陌生的。决定生活在边缘并成为 vue3 的早期采用者(我在很多方面都喜欢它)让我更容易对现在文档质量的差异感到困惑。
也就是说,这就是我的解决方案。
问题:实际问题是,按照配置,Apollo无法知道getTokens
和getToken
return相同类型 (token
).
解决方案:我发现解决这个问题的最低配置如下:
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
token(_, { args, toReference }) {
return toReference({
__typename: 'token',
id: args?.id,
});
},
},
},
},
});
但是,感觉……对我来说有点恶心。理想情况下,我希望看到一种方法,只需将 apollo 指向我的模式副本或模式自省,然后让它为我解决这个问题。如果有人知道更好的方法,请告诉我。
更好的(?)解决方案:在短期内,我认为这是一个更具可扩展性的解决方案:
type CacheRedirects = Record<string, FieldReadFunction>;
function generateCacheRedirects(types: string[]): CacheRedirects {
const redirects: CacheRedirects = {};
for (const type of types) {
redirects[type] = (_, { args, toReference }) => {
return toReference({
__typename: type,
id: args?.id,
});
};
}
return redirects;
}
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
...generateCacheRedirects(['token']),
},
},
},
});
如果有人对这些有什么改进,请加一个comment/solution! :)