GraphQL 的发展与核心特性
GraphQL 是一种用于 API 的查询语言和运行时,由 Facebook 开发并开源。它提供了一种高效、灵活的方式来获取数据,使客户端能够精确地请求所需的数据。 主要特性: - **声明式数据获取**:客户端可以明确指定需要哪些字段和嵌套结构,避免了多余的数据传输。 - **单一端点**:所有数据请求都通过一个统一的端点进行,简化了 API 的管理和调用。 - **强类型系统**:使用 Schema 定义数据结构,支持类型检查和自动文档生成。 - **实时数据支持**:通过订阅功能,可实现服务器向客户端推送实时更新。 优势: - 减少网络请求次数:通过一次请求获取多个相关资源,提升性能。 - 避免过度获取或不足获取数据:客户端只接收所需字段,减少带宽消耗。 - 更好的前端开发体验:前端开发者能更直观地理解数据结构,提高开发效率。 - 与多种平台和语言兼容:支持主流编程语言和框架。 与 REST 的区别: - REST 通常为每个资源定义多个端点(如 /users、/posts),而 GraphQL 使用单一端点处理所有请求。 - REST 返回固定结构的数据,客户端无法自定义响应内容;GraphQL 允许客户端动态指定返回的数据结构。 - REST 依赖 HTTP 方法(GET、POST 等)来操作资源,而 GraphQL 通过统一的查询语句完成读取、写入和订阅操作。 - 在复杂嵌套数据场景中,REST 可能需要多次请求,而 GraphQL 可以在单次请求中完成。 总体而言,GraphQL 更适合需要灵活数据获取、频繁交互和复杂数据结构的应用场景。
GraphQL:发展历程
GraphQL 是由 Facebook 创建的开源查询语言。在 2015 年开源之前,Facebook 自 2012 年起就在其移动应用中内部使用 GraphQL,作为对传统 REST 架构的一种替代方案。得益于 GraphQL,Facebook 移动应用的网络使用量大幅减少,数据传输效率显著提升。
假设你希望通过 REST API 获取数据,并请求:“嘿,REST API,请把所有课程的标题给我”。在这种情况下,你需要访问一个特定的端点或 URL,而这个 URL 决定了返回的数据内容。通过 REST API 请求某个 URL 后,通常会返回类似 JSON 或 JavaScript 对象的完整数据结构。这往往导致获取到大量不需要的数据,需要额外过滤才能得到所需信息,或者必须发起多次请求来满足不同的查询需求。然而,GraphQL 的工作方式完全不同。
GraphQL 有何不同?
与传统的“访问一个 URL,接收返回的所有数据”的 API 不同,GraphQL 允许你明确指定所需的数据,让客户端能够更精准地控制所接收的信息。
汉堡包类比
可以这样理解:你想吃一个只包含面包、奶酪、黄瓜和生菜的三明治。走进一家名为 RESTaurant 的餐厅,菜单上唯一的选项是“三明治”——你下单后收到的三明治里包含了面包、香肠、生菜、番茄、黄瓜和奶酪。然后你得把不需要的部分全部去掉,才能吃到自己想要的三明治——这就是 REST API 的工作方式。但当你来到 GraphQL 咖啡馆时,发现你可以自定义三明治的配料,最终拿到的正是你想要的那一款。

过度获取(Overfetching)
在 REST 架构中,后端为每个资源在每个 URL 上定义了可提供的数据,而前端则必须请求整个资源的所有信息,即使只需要其中一部分。
最糟糕的情况是,客户端应用程序需要通过多次网络请求来读取多个资源,这种现象被称为 过度获取。而 GraphQL 作为一种服务器端和客户端都支持的查询语言,允许客户端通过一次请求就决定自己真正需要哪些数据。
规范 ≠ 实现
GraphQL 是一种查询语言,用于从 API 获取数据到应用程序中,因此它本质上是一个 规范,而非 实现。最初,Facebook 开源了 GraphQL 的规范及其基于 JavaScript 的参考实现。如今,除了 JavaScript 外,已有多种编程语言支持其具体实现。围绕 GraphQL 的生态系统正在横向扩展,支持多种编程语言,同时也在纵向发展,涌现出如 Apollo 和 Relay 等基于 GraphQL 的高级库。
查询与变更操作
目前,GraphQL 的操作主要分为两大类:查询(读)和变更(写)。每种操作都只是一个字符串,需按照 GraphQL 查询语言的规范进行构造。
查询用于获取数据,变更用于修改服务器端的数据。下面的例子展示了查询的结构与其返回结果完全一致。这是 GraphQL 的核心特性之一:它始终能提供预期的结果,因为服务器清楚客户端究竟在请求什么。
1// GraphQL 查询: 2 3query { 4 course(id: "5") { 5 id 6 name 7 author 8 } 9} 10 11// 查询结果: 12 13"data": { 14 "course": { 15 "id": "5", 16 "name": "使用 React 学习 GraphQL", 17 "author": "Robin Wieruch" 18 } 19}
当这一 GraphQL 操作到达后端应用时,系统会根据完整的 GraphQL Schema 进行解析,并将对应的数据返回给前端。GraphQL 对底层网络层(通常是 HTTP)和数据格式(通常是 JSON)没有强制要求,因此它并不对整体应用架构做出任何偏好性规定。
关系型查询
借助 GraphQL,我们可以对多个字段进行关联查询,从而在一次请求中获取所有所需数据,而无需像 REST 架构那样多次请求(每个字段一次)。

在以下示例中,查询请求了多个资源(作者、文章),这些在 GraphQL 中被称为 字段。同时,它还请求了文章字段中的特定嵌套字段(名称、URL 别名),尽管该实体的 GraphQL Schema 中还包含更多数据(如 描述、发布日期)。而在 REST 架构中,获取作者及其文章至少需要两次流水线式请求,而 GraphQL 只用一次查询即可完成。此外,查询仅选择了必要的字段,而不是返回整个实体的所有内容。
1// GraphQL 查询: 2author(id: "7") { 3 id 4 name 5 avatarUrl 6 articles(limit: 2) { 7 name 8 urlSlug 9 } 10} 11 12// 查询结果: 13{ 14 "data": { 15 "author": { 16 "id": "7", 17 "name": "Robin Wieruch", 18 "avatarUrl": "https://domain.com/authors/7", 19 "articles": [ 20 { 21 "name": "学习 React 的道路", 22 "urlSlug": "the-road-to-learn-react" 23 }, 24 { 25 "name": "React 测试教程", 26 "urlSlug": "react-testing-tutorial" 27 } 28 ] 29 } 30 } 31}
这就是 GraphQL 的核心精髓。
接下来,我们将简要介绍 GraphQL 服务端与客户端的基本概念。