2017年11月28日

GraphQL 服务器基础知识:网络层

GraphQL 服务器的结构和实现(第二部分)。

GraphQL Server Basics

前一篇文章中,我们通过学习GraphQL 模式及其在执行查询和变更时的基本作用,涵盖了 GraphQL 服务器内部运作的很多方面。

虽然我们了解了 GraphQL 服务器如何使用 GraphQL 引擎执行这些操作,但我们尚未触及实际的客户端-服务器通信方面:查询及其响应如何通过网络传输的问题。 这就是本文要讨论的内容!

GraphQL 服务器可以使用您喜欢的任何编程语言来实现。本文重点介绍 JavaScript 以及可帮助您构建服务器的可用库,最值得注意的是:express-graphqlapollo-servergraphql-yoga

通过 HTTP 提供 GraphQL 服务

GraphQL 与传输层无关

关于 GraphQL,需要理解的关键一点是,它实际上与数据通过网络传输的方式无关。 这意味着 GraphQL 服务器有可能基于 HTTP 以外的协议工作,例如 WebSockets 或更底层的 TCP。 但是,本文重点介绍当今实现 GraphQL 服务器的最常见方式,这种方式确实基于 HTTP。

Express.js 被用作强大而灵活的基础

以下部分主要介绍 Express.js 及其中间件概念,该概念用于 express-graphqlapollo-server 等 GraphQL 库。如果您已经熟悉 Express,可以直接跳到下一节。

Comparison of express, hapi, koa and sail on npm trendsexpresshapikoasailnpm 趋势上的比较

Express.js 是迄今为止最受欢迎的 JavaScript Web 框架。 它以其简洁性、灵活性和性能而著称。

开始使用您自己的 Web 服务器所需的全部代码如下

使用 Node.js 执行此脚本后,您可以在浏览器中访问 https://127.0.0.1:3000 上的网站

您可以轻松地向服务器的 API 添加更多端点(也称为 路由

或使用另一种 HTTP 方法,例如 POST 而不是 GET

Express 在实现服务器方面提供了极大的灵活性,允许您使用 中间件 的概念轻松添加功能。

Express 中灵活性和模块化的关键:中间件

中间件允许拦截传入的请求并执行专用任务,同时处理请求或在返回响应之前执行。

本质上,中间件只是一个函数,它接受三个参数

  • req:来自客户端的传入请求
  • res:要返回给客户端的响应
  • next:用于调用下一个中间件的功能

由于中间件函数具有(写入)访问传入请求对象以及传出响应对象的权限,因此它们是一个非常强大的概念,可以根据特定目的塑造请求和响应。

中间件可用于许多用例,例如身份验证缓存数据转换验证自定义业务逻辑的执行等等。 这是一个简单的日志记录示例,它将打印接收请求的时间

通过这种中间件方法获得的灵活性被 graphql-expressapollo-servergraphql-yoga 等框架所利用,这些框架都基于 Express!

Express 和 GraphQL

凭借我们在上一篇文章中学到的关于 graphql 函数和 GraphQL 执行引擎的所有知识,我们已经可以预测基于 Express 的 GraphQL 服务器如何工作。

由于 Express 提供了处理 HTTP 请求所需的一切,而 GraphQL.js 提供了解析查询的功能,因此我们仍然需要它们之间的粘合剂。

这种粘合剂由 express-graphqlapollo-server 等库提供,它们只是 Express 的中间件函数!

GraphQL 中间件将 HTTP 和 GraphQL.js 粘合在一起

express-graphql:Facebook 的 GraphQL 中间件版本

express-graphql 是 Facebook 的 GraphQL 中间件版本,可与 Express 和 GraphQL.js 一起使用。 如果您查看其源代码,您会注意到它的核心功能仅在几行代码中实现。

实际上,它的主要职责是双重的

  • 确保 GraphQL.js 可以执行传入 POST 请求正文中包含的 GraphQL 查询(或变更)。 因此,它需要解析出查询并将其转发到 graphql 函数以执行。
  • 将执行结果附加到响应对象,以便可以将其返回给客户端。

使用 express-graphql,您可以按如下方式快速启动您的 GraphQL 服务器

使用 Node.js 执行此代码会在 https://127.0.0.1:4000/graphql 上启动 GraphQL 服务器

如果您阅读过关于 GraphQL 模式的前一篇文章,您将非常清楚第 7 至 18 行的用途:我们构建了一个 GraphQLSchema,它可以执行以下查询

但是,此代码片段的新部分是集成的网络层。 这次我们没有内联编写查询并直接使用 GraphQL.js 执行它(如此处所示),而是设置服务器以等待传入的查询,然后可以针对 GraphQLSchema 执行这些查询。

您真的不需要更多东西即可开始使用服务器端 GraphQL。

apollo-server:在 Express 生态系统之外更好的兼容性

从本质上讲,apollo-serverexpress-graphql 非常相似,只有一些细微的差异。 两者之间的主要区别在于,apollo-server 还允许与许多其他框架集成,例如 koahapi 以及 AWS Lambda 或 Azure Functions 等 FaaS 提供程序。 每个集成都可以通过附加包名称的相应后缀来安装,例如 apollo-server-expressapollo-server-koaapollo-server-lambda

但是,在核心方面,它也只是一个中间件,将 HTTP 层与 GraphQL.js 提供的 GraphQL 引擎桥接起来。 这是使用 apollo-server-express 对上述基于 express-graphql 的示例的等效实现

graphql-yoga:构建 GraphQL 服务器的最简单方法

消除构建 GraphQL 服务器时的摩擦

即使在使用 express-graphqlapollo-server 时,也存在各种摩擦点

  • 需要安装多个依赖项
  • 假定事先了解 Express
  • 使用 GraphQL 订阅的复杂设置

graphql-yoga 消除了这种摩擦,它是一个用于构建 GraphQL 服务器的简单库。 它本质上是 Express、apollo-server 和其他一些之上的便利层,旨在提供一种创建 GraphQL 服务器的快速方法。 (可以将其视为 GraphQL 服务器的 create-react-app。)

这是我们已经使用 express-graphqlapollo-server 看到的相同 GraphQL 服务器的外观

请注意,GraphQLServer 可以使用 GraphQLSchema 的就绪实例来实例化,也可以使用便利 API(基于 graphql-tools 中的 makeExecutableSchema)来实例化,如上面的代码片段所示。

内置支持 GraphQL Playground、订阅和追踪

请注意,graphql-yoga 还内置支持 graphql-playground。 使用上面的代码,您可以在 https://127.0.0.1:4000 打开 Playground

graphql-yoga 还具有一个简单的 API,可用于开箱即用的 GraphQL 订阅,该 API 构建于 graphql-subscriptionsws-subscriptions-transport 包之上。 您可以在这个简单的示例中查看其工作原理。

要为您使用 graphql-yoga 执行的 GraphQL 操作启用字段级分析,还内置了对 Apollo Tracing 的支持。

结论

在讨论了基于 GraphQLSchema 的 GraphQL 执行过程和 GraphQL 引擎(例如 GraphQL.js)的概念之后,在上一篇文章中,这次我们专注于网络层。 特别是,GraphQL 服务器如何通过使用执行引擎处理查询(或变更)来响应 HTTP 请求。

在 Node 生态系统中,Express 是迄今为止构建 Web 服务器的最流行框架,这归功于其简洁性和灵活性。 因此,GraphQL 服务器最常见的实现是基于 Express 的,最值得注意的是 express-graphqlapollo-server。 这两个库非常相似,只有一些细微的差异,其中最重要的一点是 apollo-server 也与其他 Web 框架(如 koahapi)兼容。

graphql-yoga 是许多其他库(例如 graphql-toolsexpressgraphql-subscriptionsgraphql-playground)之上的便利层,是构建 GraphQL 服务器的最简单方法。

在下一篇文章中,我们将讨论传递到您的 GraphQL 解析器中的 info 参数的内部结构。

不要错过下一篇文章!

注册 Prisma 新闻通讯