加入我们,于10月8日至10日在纽约市学习有关 GraphQL 联邦和 API 平台工程的最新技巧、趋势和新闻。加入我们,参加2024年在纽约市的 GraphQL 大会
文档
免费开始

配置 Apollo 客户端缓存


本文介绍缓存设置和配置。要了解如何与缓存数据交互,请参阅读取和写入缓存数据.

初始化

创建一个InMemoryCache 对象并将其提供给 ApolloClient 构造函数,如下所示:

import { InMemoryCache, ApolloClient } from '@apollo/client';
const client = new ApolloClient({
// ...other arguments...
cache: new InMemoryCache(options)
});

The InMemoryCache 构造器接受多种 配置选项.

配置选项

您可以根据需要配置缓存的行为。例如,您可以

为了自定义缓存行为,您需要在 InMemoryCache 构造函数中提供一个配置对象。此对象支持以下 .css-154yii{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-style:dotted;text-decoration-thickness:1.5px;text-decoration-color:var(--chakra-colors-gray-300);text-underline-offset:0.2em;}.css-154yii:hover,.css-154yii[data-hover]{cursor:help;}.chakra-ui-dark .css-154yii:not([data-theme]),[data-theme=dark] .css-154yii:not([data-theme]),.css-154yii[data-theme=dark]{text-decoration-color:var(--chakra-colors-blue-400);}:

名称
类型
描述
addTypename

布尔型

如果 true,缓存将自动为每个你发送的操作对象请求 __typename 字段,这意味着你可以在操作定义中省略 __typename

默认情况下,缓存将使用 __typename 字段作为缓存 ID 的一部分,以便为每个缓存对象保证获取该字段,这有助于确保字段总是被获取。

默认值是 true

resultCaching

布尔型

如果 true,只要底层数据保持不变,缓存将在每次相同的 执行时返回相同(===)响应对象。这有助于检测查询结果的更改。

默认值是 true

resultCacheMaxSize

数字

保留在内存中的结果对象的限制数量,以提高对缓存的重读速度。

默认值是 Math.pow(2, 16)

possibleTypes

对象

包含此对象以定义你模式定义中类型之间的多态关系。这样做可让你通过接口或联合查找缓存数据。

对象的每个键是一个接口或联合的 __typename,相应的值是该联合或实现该接口的类型 __typename 的数组。

有关示例,请参阅 手动定义 possibleTypes

typePolicies

对象

包含此对象以根据类型范围自定义缓存的特定行为。

对象的每个键是与要自定义的 __typename的类型的 __typename,相应的值是一个 TypePolicy 对象

dataIdFromObject

函数

这是一个函数,它接受一个响应对象并返回一个在商店中规范化数据时使用的唯一标识符。

有关详细信息,请参阅 全局自定义标识符生成

自定义缓存 ID

您可以对InMemoryCache如何生成您架构中各类型的缓存ID进行自定义(查看默认行为)。如果类型使用一个(或多个!)除了 id_id之外为其唯一的识别符。

要实现这一点,您需要为要自定义的每个类型定义一个TypePolicy。您将所有缓存typePolicies指定在提供给InMemoryCache构造函数的`options`对象中。

在相关的TypePolicy对象中包含一个keyFields 字段,如下所示:

const cache = new InMemoryCache({
typePolicies: {
Product: {
// In an inventory management system, products might be identified
// by their UPC.
keyFields: ["upc"],
},
Person: {
// In a user account system, the combination of a person's name AND email
// address might uniquely identify them.
keyFields: ["name", "email"],
},
Book: {
// If one of the keyFields is an object with fields of its own, you can
// include those nested keyFields by using a nested array of strings:
keyFields: ["title", "author", ["name"]],
},
AllProducts: {
// Singleton types that have no identifying field can use an empty
// array for their keyFields.
keyFields: [],
},
},
});

以下示例展示了具有不同keyFieldstypePolicies:

  • Product类型使用其upc字段作为其识别字段。
  • Person类型使用其nameemail字段的组合。
  • Book类型将一个子字段作为其缓存ID的一部分。
    • ["name"]项表示数组(author)中前一个字段的name字段是缓存ID的一部分。此时Bookauthor字段必须是一个包含name字段的对象,才有效。
    • 有效的Book类型的缓存ID具有以下结构:
      Book:{"title":"Fahrenheit 451","author":{"name":"Ray Bradbury"}}
  • AllProducts类型说明了针对单例类型的一种特殊策略。如果缓存将只包含一个AllProducts对象,并且该对象没有识别字段,您可以为其keyFields提供空数组。

如果对象有多个keyFields,则缓存ID始终按相同的顺序列出这些字段以确保唯一性。

请注意,这些keyFields字符串始终引用方案中定义的标准字段名称。这意味着字段别名敏感。

计算对象的缓存ID

全局定制标识生成

import { defaultDataIdFromObject } from '@apollo/client';
const cache = new InMemoryCache({
dataIdFromObject(responseObject) {
switch (responseObject.__typename) {
case 'Product': return `Product:${responseObject.upc}`;
case 'Person': return `Person:${responseObject.name}:${responseObject.email}`;
default: return defaultDataIdFromObject(responseObject);
}
}
});

此代码的缺点如下

  • 它没有任何措施来保护对未定义对象属性的访问。

定制类型策略

const cache = new InMemoryCache({
typePolicies: {
Person: {
fields: {
name: {
read(name = "UNKNOWN NAME") {
return name.toUpperCase();
}
},
},
},
},
});
// Add a type policy to the cache.
cache.policies.addTypePolicies({
Person: {
fields: {
email: {
read(email = "[email protected]") {
return email;
},
},
},
},
});

总体而言,代码为Person类型设置缓存行为,确保如果缓存中没有这些字段,则nameemail字段提供默认值。

禁用归一化

您可以指示InMemoryCache不要对特定类型的对象进行归一化。这对于由时间戳标识且永远不会接收到更新的指标和其他临时数据非常有用。

要禁用类型的归一化,为类型定义一个TypePolicy(如自定义缓存ID中所示)并设置策略的keyFields字段为false

未归一化的对象将嵌入其在缓存中的父对象中。您不能直接访问这些对象,但可以通过其父对象访问它们。

TypePolicy字段

要通过自定义缓存与模式中特定类型交互的方式,可以将映射__typename字符串到TypePolicy对象的InMemoryCache构造函数传递一个对象。

一个TypePolicy对象可以包含以下字段:

type TypePolicy = {
// Allows defining the primary key fields for this type, either using an
// array of field names, a function that returns an arbitrary string, or
// false to disable normalization for objects of this type.
keyFields?: KeySpecifier | KeyFieldsFunction | false;
// If your schema uses a custom __typename for any of the root Query,
// Mutation, and/or Subscription types (rare), set the corresponding
// field below to true to indicate that this type serves as that type.
queryType?: true,
mutationType?: true,
subscriptionType?: true,
fields?: {
[fieldName: string]:
| FieldPolicy<StoreValue>
| FieldReadFunction<StoreValue>;
}
};
// Recursive type aliases are coming in TypeScript 3.7, so this isn't the
// actual type we use, but it's what it should be:
type KeySpecifier = (string | KeySpecifier)[];
type KeyFieldsFunction = (
object: Readonly<StoreObject>,
context: {
typename: string;
selectionSet?: SelectionSetNode;
fragmentMap?: FragmentMap;
},
) => string | null | void;

重写根操作类型(不常见)

keyFields外,一个TypePolicy还可以通过设置queryTypemutationTypesubscriptionTypetrue来指示其类型代表根查询mutationsubscription类型:

const cache = new InMemoryCache({
typePolicies: {
UnconventionalRootQuery: {
// The RootQueryFragment can only match if the cache knows the __typename
// of the root query object.
queryType: true,
},
},
});
const result = cache.readQuery({
query: gql`
query MyQuery {
...RootQueryFragment
}
fragment RootQueryFragment on UnconventionalRootQuery {
field1
field2 {
subfield
}
}
`,
});
const equivalentResult = cache.readQuery({
query: gql`
query MyQuery {
field1
field2 {
subfield
}
}
`,
});

缓存通常通过在发送到服务器的每个选择集中添加__typename字段来获取__typename信息。技术上,它可以使用相同的方法为每个操作的最外层选择集获取__typename,但根查询mutation__typename几乎总是"Query""Mutation",因此缓存假设这些常用默认值,除非在TypePolicy中另有说明。

对于图中的大多数对象,来说,字段__typename对于正确识别和规范化至关重要。对于根查询和变异类型,__typename几乎没有什么用或重要,因为这些类型是单个实例,每个客户端只有一个。

fields属性

TypePolicy中,最后一个属性是fields属性,它允许您定制单个缓存的字段行为

上一页
概览
下一页
阅读和写作
评分文章评分在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,简称为Apollo GraphQL。

隐私政策

公司