graphql:Apollo Server 最佳实践 (翻译)

GraphQL 查询最佳实践:操作命名、GraphQL 变量等 创建查询和变更时,遵循以下最佳实践,以充分利用 GraphQL 和 Apollo 工具。

为所有操作命名

这两个查询获取相同的数据:

markdown 复制代码
# 推荐 ✅
query GetBooks {
  books {
    title
  }
}

# 不推荐 ❌
query {
  books {
    title
  }
}

第一个查询被命名为 GetBooks。第二个查询是匿名的。

您应该为应用中的每个 GraphQL 操作定义一个名称。这样做提供以下好处:

  • 您可以为自己和团队成员澄清每个操作的目的。
  • 当在单个查询文档中组合多个操作时,可以避免出现意外错误(匿名操作只能单独出现)。
  • 您可以改善客户端和服务器代码中的调试输出,帮助您准确识别导致问题的操作。
  • Apollo Studio 提供有用的操作级别指标,这需要命名操作。

使用 GraphQL 变量提供参数

这两个查询都可以获取 ID 为 "5" 的 Dog 对象:

bash 复制代码
# 推荐 ✅
query GetDog($dogId: ID!) {
  dog(id: $dogId) {
    name
    breed
  }
}

# 不推荐 ❌
query GetDog {
  dog(id: "5") {
    name
    breed
  }
}

第一个查询使用变量($dogId)作为 dog 字段的必需参数的值。这意味着您可以使用该查询获取任何 ID 的 Dog 对象,使其更具可重用性。

您可以像这样将变量值传递给 useQuery(或 useMutation):

php 复制代码
dog.tsx
const GET_DOG = gql`
  query GetDog($dogId: ID!) {
    dog(id: $dogId) {
      name
      breed
    }
  }
`;

function Dog({ id }) {
  const { loading, error, data } = useQuery(GET_DOG, {
    variables: {
      dogId: id
    },
  });
  // ...渲染组件...
}

硬编码 GraphQL 参数的缺点

除了可重用性之外,硬编码参数与变量相比还有其他缺点:

减少缓存效果

如果两个相同的查询有不同的硬编码参数值,它们被您的 GraphQL 服务器的缓存视为完全不同的操作。缓存使您的服务器能够跳过之前遇到的操作的解析和验证,提高性能。

服务器端缓存还支持自动持久化查询和联邦网关中的查询计划等功能。硬编码参数减少了这些功能的性能提升,并占用了缓存中有用的空间。

减少信息隐私

GraphQL 参数的值可能包含敏感信息,例如访问令牌或用户的个人信息。如果此信息包含在查询字符串中,则会与该查询字符串的其余部分一起缓存。

变量值不包含在查询字符串中。您还可以指定将哪些变量值(如果有的话)包含在向 Apollo Studio 报告的指标中。

仅查询您需要的数据,且在需要时查询

GraphQL 相比传统的 REST API 最大的优势之一是其对声明式数据获取的支持。每个组件都可以(也应该)准确查询它渲染所需的字段,不会有多余的数据通过网络发送。

如果相反,您的根组件执行一个单一的、庞大的查询以获取其所有子组件的数据,它可能会代表当前状态下甚至未渲染的组件查询。这可能导致响应延迟,并且极大地降低服务器端响应缓存重用查询结果的可能性。

在大多数情况下,如下查询应该被分解为多个查询,并分配给适当的组件:

  • 如果您有始终一起渲染的组件集合,您可以使用片段在它们之间分配单个查询的结构。参见片段共定位。
  • 如果您正在查询的列表字段返回的项目数量超过了您的组件需要渲染的数量,您应该对该字段进行分页。

分别查询全局数据和用户特定数据

某些字段无论哪个用户查询都返回完全相同的数据:

markdown 复制代码
# 返回周期表的所有元素
query GetAllElements {
  elements {
    atomicNumber
    name
    symbol
  }
}

其他字段根据查询它们的用户返回不同的数据:

bash 复制代码
# 返回当前用户的文档
query GetMyDocuments {
  myDocuments {
    id
    title
    url
    updatedAt
  }
}

为了提高服务器端响应缓存的性能,只要可能,就在单独的查询中获取这两种类型的字段。通过这样做,您的服务器可以为 GetAllElements 之类的查询缓存单个响应,同时为执行 GetMyDocuments 的每个用户缓存单独的响应。

相关推荐
忙碌54410 天前
区块链应用开发的完整实战指南:从理论到落地的企业级解决方案
架构·区块链·restful·graphql
yuki_uix20 天前
GraphQL 重塑:从 API 语言到 AI 时代的"逻辑神经系统"
前端·graphql
果粒蹬i22 天前
【HarmonyOS】RN of HarmonyOS实战开发项目+Apollo GraphQL客户端
华为·harmonyos·graphql
程序猿阿伟23 天前
《GraphQL批处理与全局缓存共享的底层逻辑》
后端·缓存·graphql
程序猿阿伟23 天前
《GraphQL状态图建模与低时延控制能力解析》
后端·graphql
程序猿阿伟24 天前
《面向第三方的GraphQL开放平台设计指南》
后端·graphql
程序猿阿伟24 天前
《GraphQL 强类型架构下的错误处理体系设计指南》
后端·架构·graphql
爬山算法1 个月前
Hibernate(78)如何在GraphQL服务中使用Hibernate?
java·hibernate·graphql
Irene19911 个月前
HTTP 请求方法选择与 RESTful 实践(对比 GraphQL、RPC)
rpc·restful·http请求·grpc·graphql
Dontla1 个月前
GraphQL介绍(声明式查询)文件上传GraphQL文件上传
后端·graphql