【译】GraphQL Server基础:网络层

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

在上一篇文章中,我们通过学习GraphQL schema及其在执行查询和变异时的基本作用,了解了很多基础的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,可以跳到下一部分。

【译注】上图截止时间为2020年1月31日。

npm趋势express, hapi, koa and sail的比较

Express.js是迄今为止最受欢迎的JavaScript Web框架。它的简洁性,灵活性和性能使其十分耀眼。

开始体验你自己的服务器只需要如下代码:

const express = require('express')
const app = express()
// respond with "hello world" when a GET request is received
app.get('/', function(req, res) {
  res.send('<h1>Hello World</h1>')
})
app.listen(3000)

使用Node.js执行此脚本后,您可以在浏览器地址栏中输入http://localhost:3000访问网站:

您可以轻松地向服务器API添加更多终结点(也称为路由):

app.get('/goodbye', function(req, res) {
  res.send('<h1>Goodbye</h1>')
})

或使用其他HTTP方法,例如POST而不是GET:

app.post('/', function(req, res) {
  res.send('<h1>You just made a POST request</h1>')
})

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

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

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

本质上,中间件不过是带有三个参数的函数:

  • req:客户端的传入请求
  • res:返回给客户端的响应
  • next:调用下一个中间件的函数

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

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

function loggingMiddleware(req, res, next) {
  console.log(`Received a request at: ${Date.now()}`)
  next()
}
app.use(loggingMiddleware)

通过这种中间件方式获得的灵活性被诸如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服务器开发:

const express = require('express')
const graphqlHTTP = require('express-graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const app = express()
const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
  name: 'Query',
  fields: {
    hello: {
      type: GraphQLString,
      resolve: (root, args, context, info) => {
        return 'Hello World'
      }
    }
  }
})
app.use('/graphql', graphqlHTTP({
  schema,
  graphiql: true // enable GraphiQL
}))
app.listen(4000)

使用Node.js执行这段代码会在http://localhost:4000/graphql启动一个GraphQL服务器。

如果您已经阅读了有关GraphQL schema的上一篇文章,那么您将很好地理解第7至18行的用途:我们构建了一个GraphQLSchema,可以执行以下查询:

query {
  hello
} # responds:  { "data": { "hello": "Hello World" } }

不过,这段代码段新的部分是集成了网络层。 这次我们不是设置内联查询并直接使用GraphQL.js(如此处所示)直接执行查询,而是设置服务器等待传入的查询,然后再针对GraphQLSchema执行该查询。

您真的不需要很多的准备工作就可以开始在服务端使用GraphQL。

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

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

然而,从根本上讲,它仍然是一个中间件,将HTTP层与GraphQL.js提供的GraphQL引擎桥接在一起。 这是上述基于express-graphql的示例的等效实现在apollo-server-express中的样子:

const express = require('express')
const bodyParser = require('body-parser')
const { graphqlExpress, graphiqlExpress } = require('apollo-server-express')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = require('graphql')
const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'Query',
    fields: {
      hello: {
        type: GraphQLString,
        resolve: (root, args, context, info) => {
          return 'Hello World'
        },
      },
    },
  }),
})
const app = express()
app.use('/graphql', bodyParser.json(), graphqlExpress({ schema }))
app.get('/graphiql', graphiqlExpress({ endpointURL: '/graphql' })) // enable GraphiQL
app.listen(4000)

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

消除构建GraphQL服务器时的阻力

即使在使用express-graphqlapollo-server时,也存在许多阻碍:

  • 需要安装多个依赖
  • 假设具备Express的先验知识
  • 使用GraphQL订阅时需要复杂的设置

可以通过graphql-yoga(一个用于构建GraphQL服务器的简单库)消除这种阻力。 它本质上是Expressapollo-server其他一些库之上的便利层,以提供创建GraphQL服务器的快速方法。 (可以将其视为类似于GraphQL服务器的create-react-app。)

下面是我们在express-graphqlapollo-server中看到的同样的GraphQL服务器代码:

const { GraphQLServer } = require('graphql-yoga')
const typeDefs = `
  type Query {
    hello: String!
  }
`
const resolvers = {
  Query: {
    hello: (root, args, context, info) => 'Hello  World',
  },
}
const server = new GraphQLServer({ typeDefs, resolvers })
server.start() // defaults to port 4000

注意这里既可以使用GraphQLSchema的现成实例来实例化GraphQLServer,也可以使用快捷的接口(基于来自graphql-toolsmakeExecutableSchema)来实例化GraphQLServer,如上面的代码段所示。

内置对GraphQL游乐场,订阅和跟踪的支持

graphql-yoga具有对graphql-playground的内置支持。 使用上面的代码,您可以在http://localhost:4000打开Playground:

graphql-yoga还具有针对现成的GraphQL订阅的简单API,该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参数的内部。

原文链接按此

https://juejin.im/post/5e339510f265da3e1d219b37

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论