【问题标题】:Why do I not have an Apollo cache-hit between a multi-response query and a single-item query for the same type?为什么我在同一类型的多响应查询和单项查询之间没有 Apollo 缓存命中?
【发布时间】:2023-04-04 01:08:01
【问题描述】:

我正在使用 @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 开发工具的屏幕截图。看起来缓存实际上正在填充标准化数据:

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

【问题讨论】:

  • 不同的条目 - tokens(....) vs token(...) - 不同的查询,没有命中(缓存如何知道查询的token(...) 应该被“解析”/识别为片段/某种类型?API 可以返回任何内容对于该查询)...但您可以通过 ids 读取规范化的缓存条目/feagments

标签: graphql apollo-client vuejs3 vue-apollo apollo-cache-inmemory


【解决方案1】:

感谢@xadm 的评论以及我收到的关于 Vue 不和谐的一些反馈,我已经解决了这个问题。真的,我的困惑是因为我对这么多这些工具不熟悉。决定生活在边缘并成为 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] = (_, { args, toReference }) => {
      return toReference({
        __typename: type,
        id: args?.id,
      });
    };
  }

  return redirects;
}

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

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

【讨论】:

    猜你喜欢
    • 2020-01-22
    • 2021-01-21
    • 2020-12-24
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 2016-12-12
    • 2016-01-19
    • 1970-01-01
    相关资源
    最近更新 更多