Envelop是一个轻量级的GraphQL插件库,允许你向GraphQL执行层添加自定义功能,而不管你使用的GraphQL服务器是什么。
像Apollo GraphQL和Graphite这样的GraphQL服务器已经有了针对平台的插件系统,并且运行良好。缺点是,如果你出于任何原因选择转移到不同的GraphQL实现,你将需要修改插件以与该特定实现一起工作。
什么是Envelop?
这就是Envelop的作用。Envelop不是一个GraphQL服务器--它是GraphQL的一个封装器,允许开发者编写与平台无关的插件。这意味着你只需要写一次插件,就可以让它与Envelop一起工作,并集成到任何GraphQL服务器。
为了学习如何实现这一点,我们将把Envelop与Fastify和Apollo GraphQL整合起来。
以下是你跟随本教程所需的内容。
设置Node应用程序
运行以下命令来安装我们需要的所有依赖项。
npm install @envelop/core fastify graphql graphql-helix --save
接下来,我们需要创建一个服务器。创建一个server.js 文件并添加以下代码。
const { envelop, useSchema, useLogger } = require('@envelop/core');
const fastify = require('fastify');
const { processRequest, getGraphQLParameters } = require('graphql-helix');
在上面的代码中,我们正在导入envelop 和它的插件。如果你使用过React Hooks,插件的命名规则你会很熟悉。Envelop插件是用前缀和use 关键字命名的。在这个例子中,我们将同时添加useSchema 和useLogger 插件。
对于初学者,我们将使用GraphQL Helix来构建我们的GraphQL服务器,以捕捉和处理对Fastify服务器的请求。
创建一个GraphQL模式
接下来,我们将创建一个schema.js 文件,在这里我们将定义我们的模式类型、突变和解析器,以便我们可以创建一个歌曲库。这个文件应该有以下内容。
const {
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
} = require("graphql");
const schema = new GraphQLSchema({
mutation: new GraphQLObjectType({
name: "Mutation",
fields: () => ({
echo: {
args: {
text: {
type: GraphQLString,
},
},
type: GraphQLString,
resolve: (_root, args) => {
return args.text;
},
},
}),
}),
query: new GraphQLObjectType({
name: "Query",
fields: () => ({
song: {
type: new GraphQLObjectType({
name: "Song",
fields: () => ({
firstVerse: {
type: GraphQLString,
resolve: () => "Singing me a song is lovely.",
},
secondVerse: {
type: GraphQLString,
resolve: () =>
new Promise((resolve) =>
setTimeout(
() => resolve("You never wanted to sing with me?"),
5000
)
),
},
}),
}),
resolve: () => ({}),
},
}),
}),
});
module.exports = schema
创建一个Fastify服务器
我们将导入刚刚创建的模式,并在server.js 中的Helix库导入后使用它,如下图所示。
const { envelop, useSchema, useLogger } = require('@envelop/core');
const fastify = require('fastify');
const { processRequest, getGraphQLParameters } = require('graphql-helix');
const mySchema = require("./mySchema"); //here
将Envelop与我们的模式进行整合
无论你使用什么GraphQL服务器和集成过程,下一步都相当简单。在我们的例子中,我们正在使用两个插件。 [useSchema()](https://github.com/dotansimha/envelop/blob/main/packages/core/src/plugins/use-schema.ts)和 [useLogger()](https://github.com/dotansimha/envelop/blob/main/packages/core/src/plugins/use-logger.ts).你可以使用任何你想要的插件 - 你只需要将插件添加到plugins 数组中,像这样。
const getEnveloped = envelop({
plugins: [useSchema(mySchema), useLogger()],
});
这是集成的一个关键部分,因为它给你提供了一个高度的抽象,并允许你将所需的组件脱钩使用。
接下来,我们需要创建一个Fastify应用程序并集成Envelop。
const fastifyApp = fastify();
const port = 3000;
fastifyApp.route({
method: ['POST'],
url: '/graphql',
async handler(req, res) {
const { parse, validate, contextFactory, execute, schema } = getEnveloped({
req,
});
const request = {
body: req.body,
headers: req.headers,
method: req.method,
query: req.query,
};
const { operationName, query, variables } = getGraphQLParameters(request);
const result = await processRequest({
operationName,
query,
variables,
request,
schema,
parse,
validate,
execute,
contextFactory,
});
if (result.type === 'RESPONSE') {
res.status(result.status);
res.send(result.payload);
} else {
res.send({ errors: [{ message: 'Not Supported' }] });
}
},
});
fastifyApp.listen(port, () => {
console.log(`GraphQL server is running on port:`, port);
});
让我们来分解一下这段代码。我们首先设置了服务器并配置了GraphQL端点。然后我们从Envelop实例中导入了parse 、contextFactory 、execute 、schema ,如下图所示。
const { parse, validate, contextFactory, execute, schema } = getEnveloped({req});
这些是Envelop中的一些参数,我们将把它们传递给Helix来处理我们的GraphQL请求。
const result = await processRequest({
operationName,
query,
variables,
request,
schema,
parse,
validate,
execute,
contextFactory,
});
现在我们可以用node server.js 命令来运行API,启动Node服务器。
用Postman测试应用程序
我们应该用Postman来测试我们的应用程序。

Postman GraphQL请求的屏幕截图。
这就是了!我们已经成功地集成了Envelop,并为Node应用程序添加了一个自定义插件。
集成Envelop和Apollo GraphQL
就像我之前提到的,你可以将Envelop与任何GraphQL服务器集成。让我们来看看使用Apollo GraphQL的实现。
在一个单独的目录中,通过运行下面的命令安装GraphQL、Apollo和GraphQL工具。
npm install @apollo/client graphql @graphql-tools/schema
创建一个单独的JavaScript文件,名为app.js ,并在其中添加以下代码。
import { ApolloServer } from 'apollo-server';
import { envelop, useSchema, useLogger } from '@envelop/core';
import { makeExecutableSchema } from '@graphql-tools/schema';
const schema = makeExecutableSchema({
typeDefs: /* GraphQL */ `
type Query {
hello: String!
}
`,
resolvers: {
Query: {
hello: () => 'World',
},
},
});
const getEnveloped = envelop({
plugins: [useSchema(schema), useLogger()],
});
const server = new ApolloServer({
executor: async requestContext => {
const { schema, execute, contextFactory } = getEnveloped({ req: requestContext.request.http });
return execute({
schema: schema,
document: requestContext.document,
contextValue: await contextFactory(),
variableValues: requestContext.request.variables,
operationName: requestContext.operationName,
});
},
});
server.listen(3000);
在上面的片段中,我们用GraphQL工具创建了一个可执行模式,用Envelop创建了一个实例,并添加了useSchema() 和useLogger() 插件。
const getEnveloped = envelop({
plugins: [useSchema(schema), useLogger()],
});
请注意,useSchema 和useLogger 都是与Envelop一起预先打包的。
最后,在Apollo服务器对象中,用Envelop对象的参数覆盖执行者对象。这就是你需要将Envelop与你的Apollo GraphQL服务器整合的全部内容。
总结
如果你用GraphQL构建应用程序,你会发现Envelop是你项目的一个重要补充。如果你喜欢保持你的代码干燥,这一点尤其正确,因为Envelop允许你编写模块化的GraphQL插件,可以在所有的GraphQL服务器实现上工作。谢谢你的阅读!
使用Envelop配置任何GraphQL服务器的文章首次出现在LogRocket博客上。