前言
GraphQL 是一种 API 查询语言,通过定义类型和字段的方式来反映应用程序的数据模型。由于其灵活性和强大的查询能力,GraphQL 成为了许多应用程序的首选 API。
在本文中,我们将学习如何使用 Fastify 和 GraphQL 来快速搭建一个实用的 GraphQL API。Fastify 是一款高效且低开销的 Web 框架,可以轻松地处理高并发的请求处理场景,而且在很多情况下,Fastify 的性能也要优于其他 Node.js Web 框架。
准备工作
在开始本文的指导之前,请确保您拥有以下工具:
- Node.js & npm
- 一个文本编辑器
创建工程
首先,我们要创建一个新的工程。打开终端,进入您希望项目保存的目录,并执行以下命令:
mkdir fastify-graphql-api && cd fastify-graphql-api npm init -y
上述命令创建了一个新的 Node.js 项目,并自动填充了 package.json 文件中的默认值。
接着,我们安装 Fastify 和必要的插件:
npm i fastify graphql fastify-autoload fastify-cors
这些插件分别是:
- Fastify:Fastify 框架本身。
- GraphQL: 实现 GraphQL API 的核心库。
- Fastify-autoload:用于自动加载在指定目录下的插件。
- Fastify-cors:用于设置跨域请求的 CORS 响应头。
创建服务
我们将创建一个名为 server.js 的文件,作为我们的 GraphQL API 服务的入口点。将以下内容保存到您的 server.js 文件中:
// www.javascriptcn.com code example
const fastify = require('fastify')({
logger: true
})
const autoload = require('fastify-autoload')
fastify.register(autoload, {
dir: `${__dirname}/plugins`
})
fastify.listen(3000, '0.0.0.0', err => {
if (err) {
fastify.log.error(err)
process.exit(1)
}
console.log(`Server listening at http://localhost:${fastify.server.address().port}`)
})这段代码引入了 Fastify 框架和我们即将使用的 Fastify-autoload 插件。我们还将创建一个 Fastify 实例并启用了日志记录功能,以便我们可以更方便地查看服务的运行情况。
我们还注册了以 plugins 目录为根目录的自动加载插件的功能,以便我们可以方便地将 API 的功能封装成独立的模块并按需引入。
最后,我们通过调用 Fastify 的 listen() 方法来启动服务器,监听在 3000 端口上。
如果一切顺利,启动服务时您应该会看到类似下面的输出:
Server listening at http://localhost:3000
请注意,如果端口 3000 已经被其他进程占用,Fastify 将会自动使用其他可用端口,而不是直接退出应用程序。
创建 GraphQL Schema
GraphQL Schema 是一个 JSON 对象,用于描述 API 服务中可以执行的操作和查询。在这个例子中,我们将创建一个简单的 GraphQL Schema,它将会暴露一个 Query 类型,允许我们查询一些假设的文章数据。
创建以下文件: plugins/graphql.js,它将是我们实际处理 GraphQL 查询请求的地方。
// www.javascriptcn.com code example
const Fastify = require('fastify')
const { makeExecutableSchema } = require('graphql-tools')
const { graphqlFastify, graphqlFastifyUpload } = require('fastify-graphql')
const { typeDefs, resolvers } = require('./schema')
const schema = makeExecutableSchema({
typeDefs,
resolvers,
})
function graphqlPlugin(fastify, options, next) {
fastify.register(graphqlFastify, {
schema,
resolverValidationOptions: {
requireResolversForResolveType: false,
},
})
next()
}
module.exports = graphqlPlugin
module.exports.graphiql = async(req, res) => {
const graphqlAddress = `http://${req.headers.host}/graphql`
const response = await Fastify()
.register(graphqlFastify, {
schema,
mocking: true,
graphiql: true,
})
.inject({
url: '/graphql',
method: 'POST',
payload: {
query: `
query {
__schema {
types {
name
}
}
}
`,
},
})
res.type('text/html').send(`
<!DOCTYPE html>
<html>
<head>
<title>Fastify GraphQL Server</title>
<style>
body {
margin: 0;
padding: 0;
background-color: #f5f5f5;
}
.container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.graphiql {
width: 100%;
height: 100%;
}
</style>
<link href="//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.css" rel="stylesheet" />
</head>
<body>
<div class="container">
<div class="graphiql"></div>
</div>
<script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
<script src="//cdn.jsdelivr.net/react/0.14.7/react.min.js"></script>
<script src="//cdn.jsdelivr.net/react/0.14.7/react-dom.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/graphiql@0.12.0/graphiql.min.js"></script>
<script>
ReactDOM.render(
React.createElement(GraphiQL, {
fetcher: GraphiQL.createFetcher({
url: '${graphqlAddress}',
fetch,
}),
}),
document.querySelector('.graphiql'),
)
</script>
</body>
</html>
`)
}这段代码创建了一个 Fastify 插件,并通过 graphqlFastify 插件将 GraphQL API 绑定到 Fastify 实例上。我们还导出了一个带有 graphiql() 的函数,用于在浏览器中显示 GraphQL 的 GraphiQL 用户界面。
该函数使用 Fastify 实例暂时启动了一个 GraphiQL 界面,以显示默认请求。用户可以在此页面上编辑请求和查询,并在“Execute Query”按钮上执行请求。
除了 GraphiQL 单页应用程序之外,此函数还将指定响应的内容类型为 text/html,以确保浏览器正确地渲染该内容。
创建数据模型
在我们能够实现 GraphQL API 之前,我们需要创建一些数据类型,并定义我们将查询的数据属性。创建以下文件: plugins/schema.js。
// www.javascriptcn.com code example
const { gql } = require('apollo-server-fastify')
const typeDefs = gql`
type Author {
id: ID!
firstName: String!
lastName: String!
}
type Post {
id: ID!
title: String!
author: Author!
}
type Query {
posts: [Post!]!
}
`
const authors = [
{
id: '1',
firstName: 'Jane',
lastName: 'Doe',
},
{
id: '2',
firstName: 'John',
lastName: 'Doe',
},
]
const posts = [
{
id: '1',
title: 'Hello World',
authorId: '1',
},
{
id: '2',
title: 'GraphQL 101',
authorId: '2',
},
]
const resolvers = {
Query: {
posts: (parent, args, context) => {
return posts.map(post => {
const author = authors.find(author => author.id === post.authorId)
return {
...post,
author,
}
})
},
},
}
module.exports = {
typeDefs,
resolvers,
}上述代码定义了 Author, Post 和 Query 三个 GraphQL 类型。Post 类型包含字段 id, title 和 author,它们都是基本数据类型。Author 由字段 id, firstName 和 lastName 组成。
Query 类型定义指定了我们要从 API 服务器中提取的属性列表。在本例中,我们仅指定 posts 属性,将它定义为返回一个 Post 数组。
最后,我们创建了一个 resolvers 对象,它包含了我们的查询函数,实际执行查询操作。
代码结构
fastify-graphql-api/ ├── node_modules/ ├── plugins/ │ ├── graphql.js │ └── schema.js ├── package.json └── server.js
运行服务
在前面的步骤中,我们已经创建了必要的文件。
现在,在终端中执行以下命令来启动 API 服务:
node server.js
当服务运行时,请在浏览器中访问 GraphiQL 用户界面,地址为 http://localhost:3000/graphiql。您应该可以看到类似以下屏幕截图的内容:

现在您可以在此页面上编辑 GraphQL 查询并执行它们。例如,您可以将以下代码复制到查询框中,并点击“Execute Query”来执行查询操作:
// www.javascriptcn.com code example
query {
posts {
id
title
author {
id
firstName
lastName
}
}
}如果一切顺利,您应该可以看到与以下响应类似的结果:
// www.javascriptcn.com code example
{
"data": {
"posts": [
{
"id": "1",
"title": "Hello World",
"author": {
"id": "1",
"firstName": "Jane",
"lastName": "Doe"
}
},
{
"id": "2",
"title": "GraphQL 101",
"author": {
"id": "2",
"firstName": "John",
"lastName": "Doe"
}
}
]
}
}结语
本文向您展示了如何快速搭建一个基于 Fastify 的 GraphQL API 服务。我们介绍了 Fastify 和 GraphQL 的基础知识和用法,并通过示例代码和步骤,让您学习到如何搭建一个 GraphQL API 服务。希望这篇文章对您有所帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d651b2a941bf7134c06e02