一篇写得很好的文章 https://webapplog.com/graphql/

最近实习的工作中涉及到了大量的前端工作,所以也接触到的大量的 REST API,之前也参与过使用 GraphQL 的项目,感觉 GraphQL 的体验更加好,所以总结下对 GraphQL 和 REST 的认识。
image.png

REST 暴露的问题

REST API 配合 JSON 格式的数据交换,在前后端分离的时代很受欢迎,因为 REST 语义明晰、易水平拓展。但是仍存在一些问题:

  • 对于后端,容易出现大量相似度很高 API,后端编码存在一定重复。例如对于用户画像,前端在不同的位置会需要不同的画像字段。
  • 对于前端,会出现请求多次 API 来获取数据的情况,增加工作量。

image.png

对于前者,比较直接简洁的方法就是,后端返回全部数据,前端按需取用。这种方式存在数据泄露的风险,且数据量过大时导致网络流量过大,且很多流量其实浪费了。

另一种方法就是后端乖乖开发新的接口/修改旧接口,迎合特定的数据请求。所以对于同一份数据,后端可能会用多个接口来返回该数据的不同部分,也就是说一个 DTO 会被转换成多个 VO 来对应每一个接口。

可以看得出,REST 本身的灵活性其实很差,一旦前端需要的 VO 结构有所改变就需要修改后端代码。

GraphQL 如何改进

GraphQL 可以说就是将 DTO 转换成 VO 这个操作进行了封装,这样后端就无需进行一个 VO 一个接口这种累赘的操作,只需要统一实现所有的数据分别是如何获得就行。

故使用 GraphQL 的服务端就只需要提供一个端点,而前端获取数据的时候通过 POST 方法,然后在报文中包含像 SQL 一样的查询语言按需获取数据。整个过程就像是在查询数据库一般,每一个 DTO 就类似数据库的一个表,最终返回的 VO 就类似使用 SQL 查询到的最终结果。

此时,后端变成了前端的“数据库”
image.png
可以看出,GraphQL 将多个 HTTP 请求聚合成了一个,多个 REST 资源变成了从某一个根位置开始的图,后端对于前端而言就像是一个图数据库。
image.png

GraphQL 使用

graphql-sample

  1. 设计数据的模型,就像定义数据库的表结构。
  2. 前端 POST 请求传递 query,描述了 schema,对应返回 VO 的结构。
  3. 后端 GraphQL 根据 schema 组装成最终的数据返回给前端。

除了直接将 GraphQL 作为后端使用,也可以将其作为一个中间件,这样就能够很好兼容后端的多种协议。
image.png

应用总结

GraphQL 进一步改进了 REST API 灵活性差的特点,使得前端的请求更加简单,后端的重复工作也减少。但其实 GraphQL 也有一个缺点,就是不方便进行客户端缓存。但是许多框架如 Apollo 等都提供了开箱即用的缓存机制。

总结下 GraphQL 的特点:

  • 声明式获取数据,将数据抽象成 schema,使得接口能够精确返回,客户端的灵活性大大提高。
  • 数据聚合,一个 GraphQL 服务暴露一个端点,客户端只需要请求一个接口,简洁明了
  • 数据传输无关,获取数据的具体方式可以灵活选择,RPC、REST、直接查询数据库、另一个 GraphQL 服务……

image.png