GraphQL与REST API架构
您应该使用哪个API?
自GraphQL规范于2015年由Facebook开源以来,它已在前端Web开发中迅速普及。 为什么这项新技术突然大受欢迎,以及GraphQL与传统REST API相比具有哪些优势? 在此博客中,我们将讨论GraphQL的设计原理,将GraphQL中的请求与REST中的相同请求进行比较,并探究GraphQL与其他体系结构相比的优势。
为了了解GraphQL作为API架构的好处,我们需要讨论API在客户端-服务器结构中的作用。 API或应用程序编程接口是一种中介,它允许服务器从客户端接收对数据的结构化请求,并为所请求的数据发送结构化响应。 有多种方法可以设计API架构。 让我们研究使GraphQL非常适合现代Web应用程序的重要基础设计原则。
GraphQL服务器的设计原理
GraphQL规范概述了5条设计原则,这使其成为现代前端开发的精心设计的解决方案。 让我们研究一下GraphQL的设计原则,以Facebook新闻提要为例。
- 查询是分层结构的,具有分层和嵌套字段,格式与查询与响应数据一对一匹配。 查询和响应的形状像树,可以查询每个项目的其他嵌套字段。 在Facebook的新闻提要中,此结构允许单个查询返回帖子列表,对每个特定帖子的评论,然后对每个评论点赞。
- 该结构以产品为中心,着重于前端希望如何接收数据,并构建交付所需的运行时。 这样一来,Facebook的新闻提要就可以向后端请求一个所需的所有数据,然后让服务器根据GraphQL的规范从不同的端点获取数据。
- 它使用特定于应用程序的类型系统,使开发人员能够确保查询使用有效类型,并且在执行之前在语法上正确。 例如,新闻提要的GraphQL模式将要求字段"用户"必须包含字符串,而"喜欢"字段必须包含数字。 如果查询尝试添加其他类型的输入,则GraphQL将在执行查询之前引发错误。
- GraphQL查询是在客户端指定的,因此客户端确切知道它将以什么格式接收数据。 这意味着,如果Facebook的新闻源对包含用户名,评论和喜欢的帖子数据的请求是前端请求的格式,则可以将其结构化在一个对象中,而不是像其他体系结构那样使用多个单独的数据。
- 带有GraphQL的服务器结构必须是自省的,或者可由GraphQL本身查询。 这将启用功能强大的开发人员工具,例如GraphiQL或GraphQL Playground,这两种工具都将使Facebook开发人员能够准确查看哪些查询和字段可供他们在服务器中使用。
为了讨论向GraphQL的转变以及这些设计原则如何带来影响开发的利益,我们将首先深入探讨传统的REST API架构,并了解该架构可能会在哪些方面出现不足。
传统的RESTful架构
REST体系结构的设计范例集中在分配HTTP请求的方法(GET,POST,PUT,PATCH,DELETE)和URL端点之间的关系上。 在REST体系结构中,方法和端点的每种组合都会评估为不同的封装功能。 如果客户端需要特定端点/方法未提供的数据,则可能需要其他请求。 REST请求返回的数据格式取决于端点-无法保证该数据将按照前端使用它的方式进行格式化。 为了使用与默认情况下从端点返回的格式不同的响应数据,必须在客户端编写数据解析和操作。
接下来,让我们看一下GraphQL规范与REST的不同之处,以及使这种新体系结构成为解决客户端和服务器之间的现代数据传递问题的独特解决方案的优势。
GraphQL架构
像RESTful API一样,GraphQL API旨在处理HTTP请求并提供对这些请求的响应。 但是,相似之处到此结束。 在REST API建立在请求方法和端点之间的连接上的情况下,GraphQL API设计为仅使用一个始终通过POST请求查询的端点,通常使用URL yourdomain.com/graphql。
达到GraphQL端点后,客户端请求的负担将完全在请求主体内处理。 该请求主体必须遵守GraphQL规范,并且API必须具有适当的服务器端逻辑来处理这些请求并提供适当的响应。 与RESTful API相比,这提供了更流畅的客户端体验,后者可能要求客户端对多个数据进行多次请求,并在数据返回后进行操作。 为了阐明GraphQL如何做到这一点,让我们细分GraphQL服务器的结构。
GraphQL服务器的结构
启用GraphQL逻辑的服务器端逻辑由具有定义的服务器功能的文档组成。 这些文档包含可执行文件和类型系统定义。 顾名思义,类型系统定义定义了可接受的类型,并格式化了每个数据字段的输入和结果。 可执行文件包含要处理的可能操作的列表,其中包括操作类型(查询,突变或预订),操作名称,要查询或写入的字段以及选择集,该选择集准确定义了将从中返回什么数据操作。 选择集为GraphQL提供了最大的增值-它们允许客户端查询特定的数据集,并接收包含所请求信息的响应:仅此而已。
有关GraphQL规范的结构和语法的更多信息,请查阅GraphQL的文档。 接下来,我们来看一下GraphQL查询的结构。
GraphQL查询的剖析
下面的GraphQL查询用于获取特定书籍的数据,包括作者的名字和姓氏。
GET /graphql?query={ books(id:12) { authors { firstName, lastName } title, yearPublished, length }
{
Query { // operation type
books (id:12) { // operation endpoint
authors { // requested fields
firstName
lastName
}
title
yearPublished
}
}
}
所有这些都可以由GraphQL服务器逻辑解析和处理的一个查询完成。 将其与REST体系结构中相同请求的结构进行比较时,GraphQL的优势开始变得清晰起来。 让我们在下面查看REST请求的结构,然后重点介绍其中的一些区别!
REST请求剖析
为了向REST API发出相同的请求,客户端需要首先向终端发出请求,该请求具有返回书籍数据的功能,并将书籍ID作为参数传递:
GET /books/12
该请求可能会返回一个包含该特定书籍的所有数据的对象,例如:
{
“title” : “The Hitchhiker's Guide to the Galaxy”,
“authorID”: 42,
“yearPublished” : 1978,
“length”: 208,
“genre”: “Science Fiction”
}
与相同的GraphQL查询的响应相比,我们的示例中的响应有两个缺点:
- REST响应包含genre和等字段的额外数据,返回的信息超出了我们的期望。
- REST要求我们再提出一个请求,以获取我们实际需要的数据:该特定作者的所有书籍。
要获取这些数据,我们需要使用authorID再次提出一个请求:
GET /authors/42
此请求的响应应包含我们正在寻找的所有数据:
{ “firstName” : “Douglas”, “lastName”: “Adams” }
现在我们有了所需的所有书籍和作者数据,通过响应进行解析的负担就在客户端。 前端应用程序现在必须以可用于其所需功能的方式组合来自不同端点的数据。
考虑到所有因素,GraphQL提供的性能优于REST API,可以为前端开发人员带来回报。 使用GraphQL规范创建服务器可能需要更多设置和编写预测性服务器端逻辑来解析和处理请求。 尽管GraphQL的安装成本可能会高于传统的REST架构,但更具可维护性的代码,强大的开发工具以及简化的客户端查询的收益通常超过了成本。