Apollo-Client - 长查询加短查询与一个查询来统治所有查询,哪个在内存方面更有意义?

Apollo-Client - Long query plus short query vs. one query to rule them all, which one makes more sense memory-wise?

我的用户查询越来越长,我正在考虑将其分成两个查询,一个 ME_QUERY 具有最常用的参数,如 userType、userName、userID,和一个 USER_QUERY 来包含用户需要的所有参数,但是 USER_QUERY 只在用户设置和支付页面中需要,而 ME_QUERY 几乎在每个组件中都使用,因为事实上ACL.

我到处都需要 userType

但我不确定将它们分成两个查询是否是个好主意,因为它们都缓存在内存中各自的space中,所以将它们分开意味着内存中的两个位置,而有一个很长的查询,会很长,但只会在内存中保留一个位置,并且在突变后更新它也会更容易。

所以问题是,我是否也需要 ME_QUERY 还是 USER_QUERY 在用户登录后已经 运行 就足够了?

以下是两个查询:

export const USER_QUERY = gql`
    query {
        user {
            uid
            avatar
            isAdmin
            projectCount
            sessions
            providers
            payments // is a long object itself
            coupon
            credits
            email
            userName
            userType
            createdAt
            hasPassword
            companyName
            vatNumber
            addressLine1
            addressLine2
            country
            companySize
        }
    }
`;

export const ME_QUERY = gql`
    query {
        user {
            uid
            avatar
            isAdmin
            email
            userName
            userType
            createdAt
        }
    }
`;

简短回答:查询拆分当然有好处,但它在于改善用户体验,并且只能通过正确配置的 InMemoryCache 来实现。

Apollo 中的查询结果已规范化:

The InMemoryCache normalizes your data before saving it to the store by splitting the result into individual objects, creating a unique identifier for each object, and storing those objects in a flattened data structure. By default, InMemoryCache will attempt to use the commonly found primary keys of id and _id for the unique identifier if they exist along with __typename on an object.

如果您在用户查询中没有看到此行为,可能是因为您的 ID 字段名为 uid 而不是 id_id。您需要实现自定义 dataIdFromObject 函数 as outlined in the docs:

import { InMemoryCache, defaultDataIdFromObject } from 'apollo-cache-inmemory'

const cache = new InMemoryCache({
  dataIdFromObject: object => {
    switch (object.__typename) {
      // or whatever your user type is called
      case 'User': return `${object.__typename}:${object.uid}`
      // other types here that don't have an id or _id 
      default: return defaultDataIdFromObject(object)
    }
  }
})

在您的问题上下文中,拥有正确配置的缓存意味着两件事:

  • 获取具有相同缓存键的对象的查询将合并其结果。
  • 突变 return 匹配现有缓存键的对象将自动更新该对象。

这意味着您可以拆分 user 查询并请求最少量的字段来初始加载您的页面并延迟请求其余字段,直到用户导航到需要这些字段的页面.您甚至可以使用 prefetching 提前获取第二个查询。

此外,如果您有更新用户的突变,只要突变 return 是一个具有匹配缓存键的对象(即在这种情况下,它包含一个 guid ),它将自动更新该对象的缓存。在这些情况下,无需重新获取查询或手动更新商店——Apollo 会为您处理这一切。

旁注:缓存中的对象列表不受上述影响。如果突变导致需要在列表中添加或删除某些内容,则 Apollo 无法推断哪些列表受到影响。在这些情况下,您会 update the cache yourself.

查询拆分可以使您的应用程序更快并改善用户体验,但由于缓存在 Apollo 中的工作方式,应该不会影响内存量或更改后更新缓存的难度。