在上一篇文章中,我们通过学习GraphQL schema及其在执行查询和变更时的基本作用,涵盖了GraphQL服务器内部工作原理的许多方面。
虽然我们学习了GraphQL服务器如何使用GraphQL引擎执行这些操作,但我们还没有触及实际的客户端-服务器通信方面:即查询及其响应如何通过网络传输的问题。这就是本文要讨论的内容!
GraphQL 服务器可以用您喜欢的任何编程语言实现。本文重点介绍 JavaScript 以及帮助您构建服务器的可用库,最主要的是:
express-graphql、apollo-server和graphql-yoga。
通过 HTTP 提供 GraphQL 服务
GraphQL 与传输层无关
理解 GraphQL 的关键一点是,它实际上与数据在网络上的传输方式无关。这意味着 GraphQL 服务器可能基于 HTTP 以外的协议工作,如 WebSockets 或更底层的 TCP。然而,本文重点介绍目前实现 GraphQL 服务器最常见的方式,即基于 HTTP。
Express.js 被用作强大而灵活的基础
以下部分主要介绍 Express.js 及其用于 GraphQL 库(如
express-graphql和apollo-server)的中间件概念。如果您已经熟悉 Express,可以跳到下一节。
npm trends 上 express、hapi、koa 和 sail 的比较
Express.js 是迄今为止最受欢迎的 JavaScript web 框架。它以其简洁性、灵活性和性能而闻名。
启动您自己的 web 服务器所需的全部代码如下所示
使用 Node.js 执行此脚本后,您可以在浏览器中访问 https://:3000 上的网站

您可以轻松地向服务器的 API 添加更多端点(也称为路由)
或者使用另一种HTTP 方法,例如 POST 而不是 GET
Express 在实现服务器方面提供了极大的灵活性,允许您使用中间件的概念轻松添加功能。
Express 灵活性和模块化的关键:中间件
中间件允许拦截传入的请求并执行特定任务,无论是在请求处理过程中还是在返回响应之前。
本质上,中间件只是一个接受三个参数的函数
req:来自客户端的传入请求res:要返回给客户端的响应next:调用下一个中间件的函数
由于中间件函数对传入的请求对象和传出的响应对象都有(写入)访问权限,因此它们是一个非常强大的概念,可以根据特定目的塑造请求和响应。
中间件可用于许多用例,例如身份验证、缓存、数据转换和验证、自定义业务逻辑执行等等。这是一个简单的日志记录示例,它将打印接收请求的时间
通过这种中间件方法获得的灵活性被 graphql-express、apollo-server 或 graphql-yoga 等框架利用,它们都基于 Express!
Express 与 GraphQL
通过我们在上一篇文章中了解到的关于 graphql 函数和一般 GraphQL 执行引擎的所有知识,我们已经可以预料到基于 Express 的 GraphQL 服务器将如何工作。
由于 Express 提供了处理 HTTP 请求所需的一切,而 GraphQL.js 提供了解析查询的功能,我们所需要的只是它们之间的桥梁。
这个桥梁由 express-graphql 和 apollo-server 等库提供,它们仅仅是 Express 的中间件函数!
GraphQL 中间件将 HTTP 和 GraphQL.js 粘合在一起
express-graphql:Facebook 的 GraphQL 中间件版本
express-graphql 是 Facebook 的 GraphQL 中间件版本,可与 Express 和 GraphQL.js 一起使用。如果您查看其源代码,您会发现其核心功能仅用几行代码实现。
实际上,它的主要职责是双重的
- 确保传入的 POST 请求正文中包含的 GraphQL 查询(或变更)可以通过 GraphQL.js 执行。因此,它需要解析查询并将其转发给
graphql函数进行执行。 - 将执行结果附加到响应对象,以便将其返回给客户端。
使用 express-graphql,您可以快速启动 GraphQL 服务器,如下所示
使用 Node.js 执行此代码将在
https://:4000/graphql上启动一个 GraphQL 服务器
如果您已经阅读了上一篇关于 GraphQL schema 的文章,您会很好地理解第 7 到 18 行的用途:我们构建了一个可以执行以下查询的 GraphQLSchema
然而,这段代码的新颖之处在于集成的网络层。这次我们不是内联编写查询并直接使用 GraphQL.js 执行(如这里所示),而是设置服务器等待传入的查询,然后可以针对 GraphQLSchema 执行这些查询。
在服务器端开始使用 GraphQL 确实不需要太多额外的东西。
apollo-server:Express 生态系统之外更好的兼容性
本质上,apollo-server 与 express-graphql 非常相似,只有一些细微差别。两者之间的主要区别在于 apollo-server 还允许与其他许多框架集成,例如 koa 和 hapi,以及 FaaS 提供商,如 AWS Lambda 或 Azure Functions。每个集成都可以通过在包名称后附加相应的后缀来安装,例如 apollo-server-express、apollo-server-koa 或 apollo-server-lambda。
然而,其核心也仅仅是一个中间件,将 HTTP 层与 GraphQL.js 提供的 GraphQL 引擎连接起来。以下是上面基于 express-graphql 的示例使用 apollo-server-express 的等效实现
graphql-yoga:构建 GraphQL 服务器最简单的方法

消除构建 GraphQL 服务器时的摩擦
即使使用 express-graphql 或 apollo-server,也存在各种痛点
- 需要安装多个依赖项
- 假设有 Express 的预备知识
- 使用 GraphQL 订阅设置复杂
这些摩擦通过 graphql-yoga 消除,这是一个用于构建 GraphQL 服务器的简单库。它本质上是 Express、apollo-server 和其他一些库之上的一个便利层,提供了一种快速创建 GraphQL 服务器的方法。(可以把它想象成 GraphQL 服务器的 create-react-app。)
以下是使用 express-graphql 和 apollo-server 我们已经看到的相同 GraphQL 服务器的样子
请注意,GraphQLServer 既可以使用现成的 GraphQLSchema 实例进行实例化,也可以使用便捷 API(基于 graphql-tools 中的 makeExecutableSchema)实例化,如上面的代码片段所示。
内置支持 GraphQL Playgrounds、订阅和追踪
请注意,graphql-yoga 还内置支持 graphql-playground。使用上面的代码,您可以在 https://:4000 打开 Playground

graphql-yoga 还具有开箱即用的 GraphQL 订阅简单 API,构建在 graphql-subscriptions 和 ws-subscriptions-transport 包之上。您可以在这个简单示例中查看它是如何工作的。
为了对使用 graphql-yoga 执行的 GraphQL 操作启用字段级分析,还内置支持 Apollo Tracing。
结论
在上一篇文章中讨论了基于 GraphQLSchema 的 GraphQL 执行过程和 GraphQL 引擎(如 GraphQL.js)的概念之后,这次我们专注于网络层。特别是,GraphQL 服务器如何通过执行引擎处理查询(或变更)来响应 HTTP 请求。
在 Node 生态系统中,Express 凭借其简洁性和灵活性,是迄今为止最流行的构建 web 服务器的框架。因此,GraphQL 服务器最常见的实现都基于 Express,最著名的包括 express-graphql 和 apollo-server。这两个库非常相似,只有一些细微差别,其中最重要的区别在于 apollo-server 也兼容其他 web 框架,如 koa 和 hapi。
graphql-yoga 是许多其他库(如 graphql-tools、express、graphql-subscriptions 和 graphql-playground)之上的一个便利层,是构建 GraphQL 服务器最简单的方法。
在下一篇文章中,我们将讨论传递到 GraphQL 解析器中的 info 参数的内部。
不要错过下一篇文章!
订阅 Prisma 新闻通讯
