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 及其在 GraphQL 库(如 express-graphqlapollo-server)中使用的中间件概念。如果您已经熟悉 Express,可以跳到下一部分。

在 npm 趋势上比较 express、hapi、koa 和 sailnpm 趋势上比较 expresshapikoasail

Express.js 是目前最流行的 JavaScript Web 框架。它以其简洁性、灵活性和高性能而著称。

您只需以下代码即可启动您自己的 Web 服务器

使用 Node.js 执行此脚本后,您可以在浏览器中访问 http://localhost: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 一起使用。如果您查看其源代码,您会发现其核心功能仅用几行代码就实现了。

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

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

使用 express-graphql,您可以快速启动 GraphQL 服务器,如下所示

使用 Node.js 执行此代码会在 http://localhost: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 引擎。以下是上述基于 express-graphql 示例的等效实现,使用 apollo-server-express

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。使用上述代码,您可以在 http://localhost:4000 打开 Playground。

graphql-yoga 还开箱即用地提供了用于 GraphQL 订阅的简单 API,它基于 graphql-subscriptionsws-subscriptions-transport 包构建。您可以在这个简单示例中查看它是如何工作的。

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

总结

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

在 Node 生态系统中,Express 以其简洁性和灵活性,是目前最流行的构建 Web 服务器的框架。因此,最常见的 GraphQL 服务器实现都基于 Express,最著名的是 express-graphqlapollo-server。这两个库非常相似,只有一些细微差异,其中最重要的一点是 apollo-server 也兼容其他 Web 框架,例如 koahapi

graphql-yoga 是在许多其他库(例如 graphql-toolsexpressgraphql-subscriptionsgraphql-playground)之上提供的一个便捷层,是构建 GraphQL 服务器最简单的方式。

在下一篇文章中,我们将讨论传入 GraphQL 解析器中的 info 参数的内部机制。

不要错过下一篇文章!

订阅 Prisma 新闻通讯

© . All rights reserved.