学习教程
缓存

缓存

¥Caching

Provide Object Identifiers so clients can build rich caches

在基于端点的 API 中,客户端可以使用 HTTP 缓存 来避免重新获取资源并识别两个资源何时相同。这些 API 中的 URL 是全局唯一标识符,客户端可以利用它来构建缓存。

¥In an endpoint-based API, clients can use HTTP caching to avoid refetching resources and to identify when two resources are the same. The URL in these APIs is a globally unique identifier that the client can leverage to build a cache.

在 GraphQL 中,没有类似 URL 的原语可以为给定对象提供全局唯一标识符。因此,API 最好公开这样的标识符供客户端用作某些类型缓存的先决条件。

¥In GraphQL, there’s no URL-like primitive that provides this globally unique identifier for a given object. Hence, it’s a best practice for the API to expose such an identifier for clients to use as a prerequisite for certain types of caching.

全局唯一 ID

¥Globally unique IDs

标准化架构中对象的标识方式

¥Standardize how objects are identified in a schema

一种可能的结构是保留一个字段(例如 id)作为全局唯一标识符。这些文档中使用的示例结构使用了这种方法:

¥One possible pattern for this is reserving a field, like id, to be a globally unique identifier. The example schema used throughout these docs uses this approach:

Operation
Response

这是客户端开发者的强大工具。与基于资源的 API 的 URL 提供全局唯一键的方式相同,此系统中的 id 字段也提供全局唯一键。

¥This is a powerful tool for client developers. In the same way that the URLs of a resource-based API provide a globally unique key, the id field in this system provides a globally unique key.

如果后端使用 UUID 之类的标识符,那么公开这个全局唯一 ID 可能会非常简单!如果后端还没有每个对象的全局唯一 ID,则 GraphQL 层可能必须构造一个。通常,这很简单,只需将类型的名称附加到 ID 并将其用作标识符即可。然后,服务器可能会通过对该 ID 进行 base64 编码使其不透明。

¥If the backend uses something like UUIDs for identifiers, then exposing this globally unique ID may be very straightforward! If the backend doesn’t have a globally unique ID for every object already, the GraphQL layer might have to construct one. Oftentimes, that’s as simple as appending the name of the type to the ID and using that as the identifier. The server might then make that ID opaque by base64-encoding it.

或者,在使用 全局对象标识 时,可以使用此 ID 与 node 模式配合使用。

¥Optionally, this ID can then be used to work with the node pattern when using global object identification.

与现有 API 的兼容性

¥Compatibility with existing APIs

为此目的使用 id 字段的一个问题是使用 GraphQL API 的客户端如何与现有 API 配合使用。例如,如果我们现有的 API 接受特定于类型的 ID,但我们的 GraphQL API 使用全局唯一 ID,那么同时使用两者可能会很棘手。

¥One concern with using the id field for this purpose is how a client using the GraphQL API would work with existing APIs. For example, if our existing API accepted a type-specific ID, but our GraphQL API uses globally unique IDs, then using both at once can be tricky.

在这些情况下,GraphQL API 可以在单独的字段中公开先前 API 的 ID。这给了我们两全其美的好处:

¥In these cases, the GraphQL API can expose the previous API’s IDs in a separate field. This gives us the best of both worlds:

  • GraphQL 客户端可以继续依赖一致的机制来获取全局唯一 ID。

    ¥GraphQL clients can continue to rely on a consistent mechanism to get a globally unique ID.

  • 需要使用我们之前的 API 的客户端也可以从对象中获取 previousApiId 并使用它。

    ¥Clients that need to work with our previous API can also fetch previousApiId from the object, and use that.

备择方案

¥Alternatives

虽然全局唯一 ID 过去已被证明是一种强大的结构,但它们并不是唯一可以使用的结构,也并不适合所有情况。客户端需要的关键功能是能够为其缓存派生全局唯一标识符。虽然让服务器派生该 ID 简化了客户端,但客户端也可以派生该标识符。这可以简单到将对象的类型(用 __typename 查询)与某些类型唯一标识符结合起来。

¥While globally unique IDs have proven to be a powerful pattern in the past, they are not the only pattern that can be used, nor are they right for every situation. The critical functionality that the client needs is the ability to derive a globally unique identifier for their caching. While having the server derive that ID simplifies the client, the client can also derive the identifier. This could be as simple as combining the type of the object (queried with __typename) with some type-unique identifier.

此外,如果用 GraphQL API 替换现有 API,那么如果 GraphQL 中的所有字段都相同(id 除外,id 已更改为全局唯一),则可能会造成混淆。这将是人们可能选择不使用 id 作为全局唯一字段的另一个原因。

¥Additionally, if replacing an existing API with a GraphQL API, then it may be confusing if all of the fields in GraphQL are the same except id, which changed to be globally unique. This would be another reason why one might choose not to use id as the globally unique field.

回顾

¥Recap

回顾这些关于使用缓存和 GraphQL API 的建议:

¥To recap these recommendations for using caching with GraphQL APIs:

  • 为对象类型定义全局唯一 ID 字段可以促进各种类型的缓存

    ¥Defining a globally unique ID field for an Object type can facilitate various types of caching