🛠 后端第一步
在后端,我们的第一个目标是创建一个GraphQL 服务器,它可以:
- 接收来自客户端的 GraphQL 查询
- 根据我们新创建的 Schema 验证 查询
- 用模拟数据填充查询到的 Schema 字段
- 将填充后的 字段 作为响应返回
The Apollo Server 库帮助我们快速、轻松地以生产就绪的方式实现此服务器。
在server/src/
文件夹中,打开 index.js
.
要创建服务器,我们将使用之前安装的 @apollo/server
包。从该包中,我们只需要命名导出 ApolloServer
,因此我们将在大括号之间声明该常量。
我们还需要使用 startStandaloneServer
函数,可以从 @apollo/server/standalone
包中导入。
在下方,我们将从 schema.js
文件中导入我们的 typeDefs
:
const { ApolloServer } = require("@apollo/server");const { startStandaloneServer } = require("@apollo/server/standalone");const typeDefs = require("./schema");
接下来,让我们设置一个 async
函数,名为 startApolloServer
。在内部,我们将创建一个 ApolloServer
类的实例,并在其选项对象中传递我们的 typeDefs
:
async function startApolloServer() {const server = new ApolloServer({ typeDefs });}
注意: 我们使用简写属性表示法,并带有隐式键,因为我们已用匹配的键(typeDefs
)命名了我们的常量。
要启动服务器,我们将使用 startStandaloneServer
函数,并将我们刚刚初始化的 server
传递给它。
async function startApolloServer() {const server = new ApolloServer({ typeDefs });startStandaloneServer(server);}
The startStandaloneServer
函数返回一个 Promise
,因此我们将 await
该调用的结果,并从结果中提取 url
属性。
async function startApolloServer() {const server = new ApolloServer({ typeDefs });const { url } = await startStandaloneServer(server);}
我们还将记录一条友好的信息,让我们知道我们的服务器确实已启动并运行!
async function startApolloServer() {const server = new ApolloServer({ typeDefs });const { url } = await startStandaloneServer(server);console.log(`🚀 Server is running!📭 Query at ${url}`);}
最后,别忘了在文件底部实际调用 startApolloServer
函数!
startApolloServer();
保存更改。从终端,我们将 启动 我们的服务器,使用 npm run start
(确保你在 server/
文件夹中)。
我们得到日志信息,以及...没有别的!我们有一个正在运行的服务器,仅此而已。它漂浮在 localhost
空间的真空中,无法访问任何数据,现在它是一个悲伤而孤独的服务器。 😿
即使我们的服务器尚未连接到任何 数据源,能够向服务器发送测试 查询 并获得有效响应将非常有用。幸运的是, ApolloServer
提供了一种使用 模拟数据 完成此操作的方法。
模拟数据
要启用模拟数据,我们需要使用两个新的包: @graphql-tools/mock
和 @graphql-tools/schema
.
让我们继续安装它们。
npm install @graphql-tools/mock @graphql-tools/schema
在顶部,我们将导入 addMocksToSchema
和 makeExecutableSchema
.
const { addMocksToSchema } = require("@graphql-tools/mock");const { makeExecutableSchema } = require("@graphql-tools/schema");
然后,我们需要调整 ApolloServer
初始化。我们将不再直接传递 typeDefs
,而是使用 schema
属性。此属性是初始化 Apollo Server 的另一种方式,这对于构建联合 子图 (在我们的 Voyage 系列中了解更多)或如果我们使用诸如 makeExecutableSchema
之类的函数(我们确实使用它!)。
作为 schema
属性的值,我们将调用 addMocksToSchema
函数并传递一个对象。此对象定义了它自己的 schema
属性,在这里我们将调用 makeExecutableSchema
函数。然后,我们将向此函数传递一个包含我们的 typeDefs
的对象。
const server = new ApolloServer({schema: addMocksToSchema({schema: makeExecutableSchema({ typeDefs }),}),});
使用此代码,我们正在从 typeDefs
生成一个可执行的 Schema,并指示 Apollo Server 用占位符值(例如,对于 String
字段 使用 Hello World
)填充每个查询到的 Schema 字段。
但是,Hello World
对于歌曲标题或作者图片的 URL 并不是一个非常现实的值!为了提供更接近现实的模拟数据,我们将定义一个 mocks
对象。此对象包含函数,这些函数提供我们希望服务器为每个查询到的 字段 返回的模拟数据。
这是我们的 mocks
对象:
const mocks = {Track: () => ({id: () => "track_01",title: () => "Astro Kitty, Space Explorer",author: () => {return {name: "Grumpy Cat",photo:"https://res.cloudinary.com/dety84pbu/image/upload/v1606816219/kitty-veyron-sm_mctf3c.jpg",};},thumbnail: () =>"https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg",length: () => 1210,modulesCount: () => 6,}),};
此对象定义了 字段 的模拟值,这些字段属于 Track
对象(包括它包含的 Author
对象)。我们将此对象传递给 ApolloServer
构造函数,如下所示:
const server = new ApolloServer({schema: addMocksToSchema({schema: makeExecutableSchema({ typeDefs }),mocks,}),});
启用模拟后,Apollo Server 始终为每个列表 字段 返回正好两项。
要一次获取更多项,比如 6 项,我们将向 mocks
对象添加一个 Query.tracksForHome
,并像这样返回一个给定长度的数组: [...new Array(6)]
.
const mocks = {Query: () => ({tracksForHome: () => [...new Array(6)],}),Track: () => ({id: () => "track_01",title: () => "Astro Kitty, Space Explorer",author: () => {return {name: "Grumpy Cat",photo:"https://res.cloudinary.com/dety84pbu/image/upload/v1606816219/kitty-veyron-sm_mctf3c.jpg",};},thumbnail: () =>"https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg",length: () => 1210,modulesCount: () => 6,}),};
创建一个模拟对象,类型为 SpaceCat
,id
为 spacecat_01,title
为 'spacecat pioneer'
现在,我们的服务器已经加载了模拟数据,我们如何运行一个 查询 来测试它是否按预期工作?在下一课中,我们将使用 Apollo Explorer 无缝构建和运行测试查询。
分享您对此课程的疑问和评论
您的反馈有助于我们改进!如果您卡住了或感到困惑,请告诉我们,我们将帮助您解决。所有评论都是公开的,必须遵守 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。
您需要一个 GitHub 帐户才能在下面发布。还没有吗? 请在我们的 Odyssey 论坛中发布。