什么时候使用 GraphQL?

2,010 阅读5分钟

本文是 《全栈开发 GraphQL + Flutter 最佳实践,文章系列》 的第 3 篇。主要介绍 GraphQL 的设计理念,及其优劣。

什么是 GraphQL?

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。 GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述,使得客户端能够准确地获得它需要的数据,而且没有任何冗余,也让 API 更容易地随着时间推移而演进,还能用于构建强大的开发者工具。

一切皆是图(Graph)

使用 GraphQL,我们可以将所有的业务建模为图

图是将很多真实世界现象变成模型的强大工具,因为它们和我们自然的心智模型和基本过程的口头描述很相似。通过 GraphQL,我们会把自己的业务领域通过定义 schema 建模成一张图;在我们的 schema 里,我们定义不同类型的节点以及它们之间是如何连接的。在客户端这边,这创建了一种类似于面向对象编程的模式:引用其他类型的类型。在服务器端,由于 GraphQL 定义了接口,我们可以在任何后端自由的使用它(无论新旧!)。

共同语言

GraphQL 并不是一种协议或者规范。它是一种语言,一种前端后端交流沟通所使用的语言。这种语言用精炼简洁的语法,降低了前后端的沟通成本。此外,这门语言还是非常严谨的,并且它的可读性较高。这就降低沟通中产生误会的可能性,减少了 Debug 的时间。

熟悉这门语言的开发者看了项目的 schema 后,立刻就知道如何发送请求,并且返回值是什么格式的。这一切甚至都用不到 2 分钟,而这个过程还是一个人独立完成的,不需要与后端沟通。

演示《掘金 APP》

我们用一个页面来展示 GraphQL 有何不同之处。目前很多 APP 都有个类似的首页,顶部是一些标签,中间显示被选中标签下的内容列表:

一般情况下,这个页面会有两个接口:

  1. 获取全部标签 - 主要用于展示顶部标签栏
  2. 根据标签获取内容列表 - 主要用于展示中间的博文列表

客户端首次进入到这个页面时会发两个请求,然后将两个请求的结果拼接起来,接着刷新页面。这是传统的做法。

那么 GraphQL 是如何实现这种功能的?

定义一个 schema:

Query 是一个入口,我们可以通过 Query 下的 tags 方法拿到部分标签:

执行:

这也是之前提到过的第一个接口“获取部分标签”。

我们再来看看第二个接口“通过标签获取博文列表”是如何实现的。

这里可以通过 Query 下的 tag 方法来获取 Tag,然后使用 Tag 下的 posts 方法来获取相应的博文列表:

这样我们就能单独调用这两个接口了。

One more thing!

此外,GraphQL 可以在一个请求里面同时获取到这两个资源:

Good Job!

不过这里还遗留了一点问题,可能细心的同学已经发现了,就是:

博文作者相关信息缺失,用户名和头像 URL 没有返回。我们现在就来修复它,通过 Post 下的 user 字段把这些信息拉取出来:

完成!

举一反三

如果我们有一个《全部标签》页面。另外,这也页面还要预览每个标签下的前 4 个博文,那要怎么做呢?

反思

当今很多页面都需要向多个资源发送请求。有的页面甚至要发 3 个以上的请求, 而且请求之间可能存在依赖关系,即:后一个请求依赖于前一个请求的结果。

如果我们使用 GraphQL,只要 schema 设计得当,一个页面至少可以减少一半的请求数,而且不需要后端单独为页面出定制化的接口。

由于 GraphQL 请求配置相当灵活,我们可以通过 schema 的定义, 自己组合出各式各样的请求。这在一定程度上也减少了后端的工作量。项目做到中后期,我们会发现许多新增的需求,都不需要单独出接口,复用之前的接口就行了。例如:举一反三中提到的《全部标签+预览标签下博文》的需求。

GraphQL 优势

  • 请求你所要的数据,不多,也不少
  • 节省带宽
  • API 演进无需划分版本
  • 健全的类型系统
    • 自动生成文档
    • 减少前后端的沟通成本
  • 工具
    • GraphiQL - GraphQL 游乐场
    • Code Generater - 前端(Web 和 原生移动端)生成请求代码,而且入参和返回值都是强类型的

GraphQL 劣势

  • 学习成本,因为需要学一门新的语言 GraphQL
  • 团队合作模式改变
  • 前端压力变小,但服务器压力变大,因为部分前端压力转移到服务器上去了
  • 获取数据的效率下降,需要借助 dataloader 这样的工具来做优化

谁在使用 GraphQL?

参考

GraphQL

schema

关于 Graphs 的思考