写在前面
GraphQL 是一种新的 API 标准, 它提供了一种更高效, 强大和灵活的数据提供方式. 它是由 Facebook 开发和开源, 目前由来自世界各地的大公司和个人维护. GraphQL 本质上是一种基于 api 的查询语言, 现在大多数应用程序都需要从服务器中获取数据, 这些数据存储可能存储在数据库中, API 的职责是提供与应用程序需求相匹配的存储数据的接口. 有的人经常把 GraphQL 和数据库技术相混淆, 这是一个误解, GraphQL 是 api 的查询语言, 而不是数据库. 从这个意义上说, 它是数据库无关的, 而且可以在使用 API 的任何环境中有效使用, 我们可以理解为 GraphQL 是基于 API 之上的一层封装, 目的是为了更好, 更灵活的适用于业务的需求变化.
GraphQL 出现的历史背景
当提起 API 设计的时候, 大家通常会想到 SOAP,RESTful 等设计方式, 从 2000 年 RESTful 的理论被提出的时候, 在业界引起了很大反响, 因为这种设计理念更易于用户的使用, 所以便很快的被大家所接受. 我们知道 REST 是一种从服务器公开数据的流行方式. 当 REST 的概念被提及出来时, 客户端应用程序对数据的需求相对简单, 而开发的速度并没有达到今天的水平. 因此 REST 对于许多应用程序来说是非常适合的. 然而在业务越发复杂, 客户对系统的扩展性有了更高的要求时, API 环境发生了巨大的变化. 特别是从下面三个方面在挑战 api 设计的方式:
1. 移动端用户的爆发式增长需要更高效的数据加载
Facebook 开发 GraphQL 的最初原因是移动用户的增加, 低功耗设备和松散的网络. GraphQL 最小化了需要网络传输的数据量, 从而极大地改善了在这些条件下运行的应用程序.
2. 各种不同的前端框架和平台
前端框架和平台运行客户端应用程序的异构环境使得我们在构建和维护一个符合所有需求的 API 变得困难, 使用 GraphQL 每个客户机都可以精确地访问它需要的数据.
3. 在不同前端框架, 不同平台下想要加快产品快速开发变的越来越难
持续部署已经成为许多公司的标准, 快速的迭代和频繁的产品更新是必不可少的. 对于 REST api, 服务器公开数据的方式常常需要修改, 以满足客户端的特定需求和设计更改. 这阻碍了快速开发实践和产品迭代.
GraphQL 的出现不仅仅是针对开发人员的, Facebook 在 2012 年开始在其 native mobile apps 中使用 GraphQL. 但有趣的是 GraphQL 大部分都是在 web 技术的背景下使用的, 并且在 native mobile 领域中只得到很少的支持. Facebook 第一次公开谈论 GraphQL 是在宣布开源计划后不久的 2015 年 React 峰会的时候. 因为 Facebook 总是在 React 的背景下谈 GraphQL, 所以对于没有 React 经验的开发人员来说, 要理解 GraphQL 并不是一种仅限于 React 使用的技术可能还需要一段时间. 即便是在这样的背景下诞生的 GraphQL 依然是一个快速增长的社区 , 事实上 GraphQL 是一种技术, 可以在客户端与 API 通信的任何地方使用. 有趣的是 Netflix 和 Coursera 等其他公司都在研究类似的想法以提高 API 的交互效率. Coursera 设想了一种类似的技术, 可以让客户指定其数据需求, 而 Netflix 甚至将其解决方案称为 Falcor. 在 GraphQL 被开源之后, Coursera 完全停止了他们在 Falcor 上的努力, 并转到了 GraphQL 的学习上. 目前已经有很多的公司在使用 GraphQL(https://graphql.org/users/).
GraphQL 和 RESTful 的区别
前面提到 GraphQL 可以理解为基于 RESTful 的一种封装, 目的在于构建使 Client 更加易用的服务, 可以说 GraphQL 是更好的 RESTful 设计. 在过去的十多年中, REST 已经成为设计 web api 的标准(虽然只是一个模糊的标准). 它提供了一些很棒的想法, 比如无状态服务器和结构化的资源访问. 然而 REST api 表现得过于僵化, 无法跟上访问它们的客户的快速变化的需求. GraphQL 的开发是为了应付更多的灵活性和效率, 它解决了与 REST api 交互时开发人员所经历的许多缺点和低效之处. 为了说明在从 API 获取数据时 REST 和 GraphQL 之间的主要区别, 让我们考虑一个简单的示例场景: 在 blog 应用程序中, 应用程序需要显示特定用户的文章的标题. 同一屏幕还显示该用户最后 3 个关注者的名称. REST 和 GraphQL 如何解决这种情况?
使用 REST API 来现实时, 我们通常可以通过访问多次请求来收集数据. 比如在这个示例中, 我们可以通过下面的三步来实现:
1. 通过 /user/<id > 获取初始用户数据
2. 通过 / user/<id>/posts 返回用户的所有帖子
3. 请求 / user/<id>/followers, 返回每个用户的关注者列表
调用关系如下图所示:
如果用 GraphQL 的话, 我们只需要一次请求就可以完成上述的需求
在 GraphQL 的世界里我们不用多取数据, 也不用担心数据取少了, 我们只需要按需获取即可.
REST 最常见的问题之一是 API 的返回数据过多或者过少, 这是因为客户端下载数据的唯一方法是通过访问返回固定数据结构的 endpoint, 这就会导致我们设计 API 非常困难, 因为它既要能够为客户提供精确的数据需求, 又需要满足不同调用者的需求, 这本身就是相互矛盾的. GraphQL 的发明者 Lee Byron 提出了一个很重要的概念: "用图形来思考, 而不是 endpoint"
通过上述直观展示我们可以得出一下几点:
1. 获取了许多多余的数据
通常情况下我们在调用一个通用 API 接口时, 客户端获取的信息比应用程序中实际需要的要多. 例如 UI 需要显示一个用户列表, 而实际上只需要使用他们的名字. 在 REST API 中通常会调用 /user 这个 endpoint, 并接收一个带有用户数据的 JSON 数组. 但是这个响应可能包含更多关于返回的用户的信息, 例如他们的生日或地址, 而这些信息对客户来说是无用的, 因为它只需要显示用户的名字.
2. 获取的数据少于 Client 所需要的数据
一般来说数据获取不足意味着某个特定的 endpoint 没有提供客户端需要的足够信息, 客户端将需要额外的请求来获取它所需要的一切. 这可能会升级到客户端需要首先获取列表信息, 然后需要对单条数据添加一个额外的请求以获取其他所需的数据, 例如考虑其他 Client 也需要显示每个用户的最后三个关注者, 该 API 提供了额外的 endpoint /user/<userid>/followers, 为了能够显示所需的信息, Client 必须向 /users endpoint 发出一个请求, 然后点击 / user/<user-id>/follwers endpoint 来获取单个用户的 follwers 信息.
3. 前端的快速产品迭代对 API 有很大的挑战
REST api 的一个常见模式是根据您在应用程序内部的展现逻辑来构造 endpoint, 这很方便, 因为它允许客户端通过访问相应的 endpoint 获取特定视图的所有所需信息. 这种方法的主要缺点是它不允许前端的快速迭代. 对于 UI 所做的每一个更改, 现在都存在比以前更多 (或更少) 的数据的高风险. 因此, 需要对后端进行调整, 以满足新的数据需求, 这会降低生产力并显著降低将用户反馈集成到产品中的能力. 使用 GraphQL 这个问题就解决了. 由于 GraphQL 的灵活性, 无需在服务器上额外工作就可以在客户端上进行更改. 由于客户端可以指定准确的数据需求, 所以当前端的设计和数据需求发生变化时, 并不需要后端 API 做出任何的修改就可以满足展现层的变化.
4. Schema 和类型系统的好处
GraphQL 使用强大的 Type System 来定义 API 的功能. 所有在 API 中公开的类型都是使用 GraphQL schema Definition Language (SDL)在模式中编写的. 该模式充当客户端和服务器之间的契约, 以定义客户机如何访问数据. 一旦定义了模式, 在前端和后端工作的团队就可以在没有进一步通信的情况下完成工作, 因为他们都知道通过网络发送的数据的确切结构. 前端团队可以通过 mock 所需的数据结构来轻松测试他们的应用程序. 一旦后端 API 实现完成, 就可以对客户端应用程序进行切换来调用实际的 API 获取数据, 这也可以使得我们实现更好的客户端和服务端的分离.
写在最后
我们可以看出 GraphQL 的出现可以使得我们后端 API 具有更大的灵活性以及扩展性以满足不同 client 对数据的需要, 这大大丰富了 API 的数据提供的能力.
来源: https://www.cnblogs.com/Wolfmanlq/p/9094418.html