GraphQL 简介

简介

作者选择免费和开源Fund接受捐赠]作为编写捐赠计划的一部分。

随着Web和移动应用程序变得更加成熟和复杂,软件工程师发明了聪明的新方法来改善应用程序中客户端和服务器之间的交互。过去几年在这方面最大的范式转变之一是GraphQL,,一种用于操作API的开源查询语言和运行时。GraphQL由Facebook于2012年设计(并于2015年公开发布),旨在通过创建一个声明性、客户端驱动和性能良好的新系统来解决传统REST架构的各种弱点。

在本文中,您将回顾什么是GraphQL,熟悉GraphQL的重要术语和概念,并了解GraphQL规范与REST架构风格的比较。

什么是GraphQL?

GraphQL代表GRAPH* ** Q 查询** L** 语言,但与其他查询语言如SQL(** S** 结构化** Q** 查询** L** 语言)不同,它不是一种直接与数据库通信的语言,而是一种定义客户端与接口服务器通信的契约的语言。GraphQL规范是一种描述语言规则和特征的开放标准。它还提供了执行GraphQL查询的说明。

由于GraphQL是由一个开放标准定义的,因此没有GraphQL的官方实现。GraphQL实现可以用任何编程语言编写,与任何类型的数据库集成,并支持任何客户端(如移动或Web应用程序),只要它遵循规范中概述的规则。最流行的商业GraphQL实现之一是Apollo GraphQL,它包含几个GraphQL客户端和服务器实现,但使用或理解GraphQL并不一定要使用Apollo。

GraphQL特征

GraphQL设计有几个关键特征。GraphQL查询是声明性的和分层的,而GraphQL模式是强类型的和自省的。

声明式

GraphQL查询是_DECLARATIONAL_,这意味着客户端将确切地声明它感兴趣的字段,并且响应将只包括那些属性。

假想的奇幻游戏API的这个示例GraphQL查询请求ID为1wizard,并请求该对象上的namerace字段。

1{
2  wizard(id: "1") {
3    name
4    race
5  }
6}

JSON格式返回的响应将返回一个包含找到的wizard对象的data对象,以及查询请求的两个字段。

1{
2  "data": {
3    "wizard": {
4      "name": "Merlin",
5      "race": "HUMAN"
6    }
7  }
8}

由于GraphQL响应只为您提供所需的确切信息,因此与总是提供完整数据集的替代方案相比,它会产生更高效、更高性能的网络请求。

分层

图形QL查询也是_Hierarchy_。返回的数据遵循查询的形状。在本例中,查询已扩展为包括spells,并请求每个拼写的nameattack字段。

1{
2  wizard(id: "1") {
3    name
4    spells {
5      name
6      attack
7    }
8  }
9}

响应现在将包括与此特定wizard相关联的所有spell对象的数组。虽然wizardsspells可能存储在单独的数据库表中,但它们可以通过单个GraphQL请求获取。(然而,GraphQL并没有对数据本身是如何存储的发表意见,所以这是一个假设。

 1{
 2  "data": {
 3    "wizard": {
 4      "name": "Merlin",
 5      "spells": [
 6        {
 7          "name": "Lightning Bolt",
 8          "attack": 2
 9        },
10        {
11          "name": "Ice Storm",
12          "attack": 2
13        },
14        {
15          "name": "Fireball",
16          "attack": 3
17        }
18      ]
19    }
20  }
21}

强类型

GraphQL是强类型的,如GraphQL Type system.]所述类型描述了GraphQL服务器中的值的功能。大多数程序员都熟悉GraphQL类型,包括字符串、布尔值和数字整数等标量(原始值),以及对象等更高级的值。

本例创建一个Spell对象类型,其中的字段分别对应于StringInt标量类型。

1type Spell {
2  name: String!
3  attack: Int
4  range: Int
5}

GraphQL架构是使用类型系统定义的,它允许服务器在尝试查询数据之前确定查询是否有效。GraphQLValidation确保请求在语法上是正确的、明确的和没有错误的。

自我记录

Introspection特性允许GraphQL客户端和工具向GraphQL服务器查询底层模式的形状和数据。这允许创建GraphiQL,这样的工具,它是一个浏览器中的集成开发环境和游乐场,用于处理GraphQL查询,以及其他用于自动生成文档的工具。

例如,您可以通过__方案通过该自省功能了解有关Spell类型的更多信息。

1{
2  __schema {
3    types {
4      name
5      kind
6      description
7    }
8  }
9}

与任何其他GraphQL响应一样,响应也将是JSON:

 1{
 2  "data": {
 3    "__schema": {
 4      "types": [
 5        {
 6          "name": "Spell",
 7          "kind": "OBJECT",
 8          "description": "A powerful spell that a wizard can read from a scroll."
 9        }
10      ]
11    }
12  }
13}

客户驱动

开发GraphQL API的工作发生在后端,在那里定义和实现模式。然而,由于GraphQL API的所有功能都包含在服务器上的单个端点中,因此它由客户端通过声明性查询来决定它到底需要什么数据。这使开发人员能够快速迭代,因为前端开发人员可以继续查询GraphQL API公开的数据,而无需进行任何额外的后端工作。

架构

GraphQL存在于客户端和数据之间的应用层。GraphQL_SERVER_描述API中公开的能力,而_CLIENT_描述请求的要求。

服务器

GraphQL API定义了一个端点,通常是/graph ql端点,它可以访问GraphQL服务器的全部功能。由于GraphQL是一种应用层技术,并且与传输无关,因此它可以通过任何协议提供,但最常见的是通过HTTP提供服务。

GraphQL服务器实现可以使用任何编程语言编写,例如express-graphql中间件,它允许您在Node/Express HTTP服务器上创建GraphQL API。GraphQL也与数据库无关,应用程序的数据可以存储在MySQLPostgreSQLMongoDB或任何其他数据库中。数据甚至可以由几个传统REST API端点的聚合提供。重要的是数据是在GraphQL _schema_中定义的,它通过描述可查询的数据来定义API。

客户端

向GraphQL服务器发出的请求被称为_documents_,由_queries_(用于读取请求)和_mutations_(用于写入请求)等操作组成。

虽然有高级的GraphQL客户端,如Apollo Client或Facebook的Relay),它们提供缓存机制和其他工具,但不需要特殊的客户端向GraphQL服务器发出请求。Web浏览器中的一个简单的XMLHttpRequestfetch就足以通过将GraphQL文档发送到GraphQL服务器来发出请求。

下面是对/graph ql端点的fetch请求的示例,该端点在POST请求的正文中以字符串的形式传递GraphQL文档。

 1async function fetchWizards() {
 2  const response = await fetch('/graphql', {
 3    method: 'POST',
 4    headers: {
 5      'Content-Type': 'application/json',
 6    },
 7    body: JSON.stringify({
 8      query: `{
 9    wizards {
10      id
11      name
12    },
13  }`,
14    }),
15  })
16  const wizards = await response.json()
17
18  return wizards
19}
20
21fetchWizards()

这将为该请求返回一个JSON响应。

1{
2  "data": {
3    "wizards": [
4      { "id": "1", "name": "Merlin" },
5      { "id": "2", "name": "Gandalf" }
6    ]
7  }
8}

GraphQL与REST

GraphQL和REST是不可互换的概念,但它们解决了应用程序的类似问题。REST代表 Re presentational** S** tate** T** transfer,是一种用于在不同系统之间共享数据的软件架构风格。RESTful API是一种遵循REST原则和约束的API,包括无状态、可缓存、在客户端和服务器之间强制分离关注点,以及具有统一接口(例如通过URI)。如前所述,GraphQL是一种查询语言和执行查询的运行时规范。

这两种系统各有优缺点,在现代API开发中都有各自的用途。然而,开发GraphQL是为了克服REST系统的一些公认的弱点,并创建一个更高效的、客户端驱动的API。

  • 架构 -REST API通常由服务器上的多个端点定义,但GraphQL通过单个端点交换数据。GraphQL端点可以返回可能需要多个REST查询的复杂数据图,从而减少网络上对单个视图的请求数量。
  • 数据拉取 -REST API返回服务器端确定的数据集。这可能是太多的数据,例如,如果视图只需要响应中的一个属性。这可能还不够,比如List端点不返回表在视图中所需的所有属性。GraphQL通过声明性查询防止了这种过度和过度的数据获取。
  • 错误处理 -由于GraphQL不需要通过HTTP提供服务,因此没有使用HTTP响应码来处理错误的规范。通常,所有GraphQL端点都将使用200HTTP代码响应进行解析,失败的结果将在响应中除了data属性之外还包含一个errors属性。另一方面,REST风格的API使用不同的400级别的HTTP代码来处理客户端错误,并使用200级别的HTTP代码来成功响应。
  • 版本控制 -GraphQL API力求向后兼容,避免破坏更改,这与常见的版本控制端点的REST模式形成对比,通常使用URL本身的/v1/v2来确定版本。然而,可以使用GraphQL实现您自己的版本控制,或者使用REST通过演进实现版本,只是不那么传统而已。
  • 缓存 -可缓存性是其余部分中不可或缺的一部分指导constraints.由于基于HTTP的REST API由使用不同HTTP方法的多个端点组成,因此它可以利用现有的HTTP约定来缓存和避免重新获取资源。因为基本上每个GraphQL请求都是不同的,但是使用单个端点,所以它不能利用任何内置的HTTP缓存机制。GraphQL客户端可以利用全局对象Identification]来实现简单缓存。

这个列表没有涵盖REST和GraphQL之间的所有异同,但总结了许多最关键的要点。此外,GraphQL可以用作聚合多个REST端点或服务的网关,在这种情况下,两种技术可以和谐地并排使用。

功能|GraphQL|REST |-|---------------------------------------------------------------| 说明|GraphQL是API的查询语言,是服务端的运行时|一种设计Web服务的架构风格 数据拉取|单个响应确定性查询的HTTP端点|一组通常返回预定数据集的HTTP端点 版本控制|不鼓励版本控制|版本控制常见 HTTP状态码|包括错误在内的所有响应通常都是200|实现了HTTP状态码 Validation|内置元数据验证|验证必须手动实现 文档|内置类型系统和自省|非自文档,提供OpenAPI等工具 缓存|不支持|支持 请求方法|查询、突变、订阅(对于HTTP超过POST)|所有使用的HTTP方法(GETPOSTPATCHPUTDELETE等) 响应Content-Type|JSON|Any(JSON、XML、Html等)

结论

GraphQL是一种开源的查询语言和API运行时。GraphQL是由Facebook的开发人员发明的,目的是通过为API创建客户端驱动的声明性查询语言来解决传统REST API遇到的各种问题,如过度/不足获取数据和低效的网络请求。

虽然GraphQL不是一个可以与REST互换的概念,但它们都描述了管理客户端和服务器之间通信的不同方式。在本文中,您了解了什么是GraphQL、GraphQL和REST之间的主要区别和相似之处,以及GraphQL服务器如何向客户端公开数据。

本教程是我们的如何使用GraphQL管理数据》系列的一部分,该系列介绍了GraphQL的基础知识。

Published At
Categories with 技术
comments powered by Disqus