微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么在同一类型的多响应查询和单项查询之间没有 Apollo 缓存命中?

如何解决为什么在同一类型的多响应查询和单项查询之间没有 Apollo 缓存命中?

我正在使用 @vue/apollo-composable@graphql-codegen 开发一个 vue3 项目。

我的索引页执行搜索查询。该查询的每个结果在页面上都有一个磁贴。我期待 tile 查询会由缓存回答,但相反,它们总是错过。

页面级别我做这个查询

query getTokens($limit: Int!) {
    tokens(limit: $limit) {
        ...tokenInfo
    }
}

在我执行的 tile 组件内部:

query getToken($id: uuid!){
    token(id: $id) {
        ...tokenInfo
    }
}

片段看起来像这样:

fragment tokenInfo on token {
    id
    name
}

期望:缓存将处理 100% 的 tile 组件内的查询。 (我希望避免将这些数据序列化为 vuex 的失败)。

现实:我接到了 n+1 个后端调用。我已经尝试了一堆排列,包括摆脱片段。如果我发送带有 getTokenfetchPolicy: 'cache-only' 调用,则不会返回任何数据。

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 开发工具的屏幕截图。看来缓存实际上填充了规范化数据:

apollo-cache-screenshot

任何帮助将不胜感激! :)

解决方法

感谢@xadm 的评论以及我在 Vue discord 上收到的一些反馈,我已经解决了这个问题。真的,我的困惑归结于我对这么多这些工具不熟悉。决定生活在边缘并成为 vue3 的早期采用者(我在很多方面都喜欢它)让我更容易对现在文档质量的差异感到困惑。

也就是说,这是我的解决方案。

问题:实际问题是,按照配置,Apollo 无法知道 getTokensgetToken 返回相同的类型 (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] = (_,toReference }) => {
      return toReference({
        __typename: type,});
    };
  }

  return redirects;
}

const cache = new InMemoryCache({
  typePolicies: {
    Query: {
      fields: {
        ...generateCacheRedirects(['token']),});

如果有人对这些有任何改进,请添加评论/解决方案! :)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。