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 中的工作方式,应该不会影响内存量或更改后更新缓存的难度。
我的用户查询越来越长,我正在考虑将其分成两个查询,一个 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 中的工作方式,应该不会影响内存量或更改后更新缓存的难度。