Skip to content

GraphQL - 示例

在本章中,我们将使用现代工具构建一个最小但功能完整的 GraphQL API。这个 API 将返回一个简单的问候消息 ‘Hello GraphQL World!’,我们将使用 Apollo Sandbox(一个浏览器内的 GraphQL IDE)访问它。

创建一个独立的 GraphQL 服务器,使用 Node.js、Express 和 Apollo Server 4,响应一个简单的 greeting 查询。

  • Node.js: JavaScript 运行时环境。
  • Express: 用于 Node.js 的极简 Web 应用框架。
  • @apollo/server: 构建 GraphQL 服务器的核心库。
  • graphql: GraphQL 的 JavaScript 参考实现。
  • Schema Definition Language (SDL): 用于定义 API 的结构。
  • Resolvers: 为 Schema 字段提供数据的函数。

创建一个新的项目文件夹(例如 hello-graphql-server)并初始化它:

mkdir hello-graphql-server
cd hello-graphql-server
npm init -y

安装必要的依赖:

npm install @apollo/server graphql express cors body-parser

这将安装 Apollo Server 4、GraphQL.js、Express,以及用于 CORS 和 JSON 请求体解析的中间件。

定义你的 GraphQL Schema。为了简单起见,我们将直接在服务器文件中将其定义为一个字符串。在大型项目中,通常会将其放在单独的 .graphql 文件中。

// In server.js (or a separate schema.js file)
// 在 server.js (或单独的 schema.js 文件) 中
const typeDefs = `#graphql
# This "Query" type defines all the available entry points for reading data.
# "Query" 类型定义了所有可用的数据读取入口点。
type Query {
# This query takes no arguments and returns a String
# 这个查询不接受参数并返回一个 String 类型的值
greeting: String
}
`;

这个 Schema 定义了一个名为 greeting 的查询字段,它返回一个非空的 String 类型值。

Resolvers(解析器)是为 Schema 中的字段提供实际数据的函数。解析器对象的结构应镜像 Schema 的结构。

// In server.js (or a separate resolvers.js file)
// 在 server.js (或单独的 resolvers.js 文件) 中
const resolvers = {
// Resolvers for the Query type
// Query 类型的解析器
Query: {
// Resolver function for the 'greeting' field
// 'greeting' 字段的解析器函数
greeting: () => {
// This function simply returns the string we want
// 这个函数只返回我们想要的字符串
return 'Hello GraphQL World!';
},
},
};

这个解析器对象为 Query 类型中的 greeting 字段提供了一个函数。

第四步:使用 Express 设置 Apollo Server

Section titled “第四步:使用 Express 设置 Apollo Server”

创建一个 server.js 文件(如果尚未创建),并组合 Schema、Resolvers 和服务器设置:

import { ApolloServer } from '@apollo/server';
import { expressMiddleware } from '@apollo/server/express4';
import { ApolloServerPluginDrainHttpServer } from '@apollo/server/plugin/drainHttpServer';
import express from 'express';
import http from 'http';
import cors from 'cors';
import bodyParser from 'body-parser';
// Define Schema (as shown in Step 2)
// 定义 Schema(如第二步所示)
const typeDefs = `#graphql
type Query {
greeting: String
}
`;
// Define Resolvers (as shown in Step 3)
// 定义 Resolvers(如第三步所示)
const resolvers = {
Query: {
greeting: () => 'Hello GraphQL World!',
},
};
// Required logic for integrating with Express
// 与 Express 集成所需的逻辑
const app = express();
// Our httpServer handles incoming requests to our Express app.
// 我们的 httpServer 处理进入 Express 应用的请求。
// Below, we drain the httpServer when the application is shut down.
// 下面,我们在应用关闭时“排出”httpServer。
const httpServer = http.createServer(app);
// Same ApolloServer initialization as before, plus the drain plugin
// 与之前相同的 ApolloServer 初始化,加上用于 httpServer 的 drain 插件。
// for our httpServer.
const server = new ApolloServer({
typeDefs,
resolvers,
plugins: [ApolloServerPluginDrainHttpServer({ httpServer })],
});
// Ensure we wait for our server to start
// 确保我们等待服务器启动
await server.start();
// Set up our Express middleware to handle CORS, body parsing,
// 设置我们的 Express 中间件来处理 CORS、请求体解析,
// and our expressMiddleware function.
// 以及我们的 expressMiddleware 函数。
app.use(
'/graphql', // Endpoint path for GraphQL requests
// GraphQL 请求的接口路径
cors(), // Enable Cross-Origin Resource Sharing
// 启用跨域资源共享
bodyParser.json(), // Parse JSON bodies
// 解析 JSON 请求体
// expressMiddleware accepts the same arguments: an Apollo Server instance and optional configuration options
// expressMiddleware 接受相同的参数:一个 Apollo Server 实例和可选的配置选项
expressMiddleware(server, {
context: async ({ req }) => ({ token: req.headers.token }), // Example context
// 示例 context
}),
);
const PORT = process.env.PORT || 9000;
// Modified server startup
// 修改后的服务器启动逻辑
await new Promise((resolve) => httpServer.listen({ port: PORT }, resolve));
console.log(`🚀 Server ready at http://localhost:${PORT}/graphql`);

这段代码初始化了 Express,创建了一个 HTTP 服务器,使用 Schema 和 Resolvers 设置了 Apollo Server,应用了必要的中间件(CORS、JSON 解析),并使用 expressMiddleware 将 Apollo Server 集成到 Express 的 /graphql 路径下。

将启动脚本添加到你的 package.json 中(如果尚未添加):

"scripts": {
"start": "node server.js"
// Requires Node.js v14.13.1+ for top-level await or wrap in async function
// 需要 Node.js v14.13.1+ 支持顶层 await,否则需要将其包裹在 async 函数中
}

在终端中运行服务器:

npm start

你应该看到消息:🚀 Server ready at http://localhost:9000/graphql

打开你的 Web 浏览器,导航到 http://localhost:9000/graphql。

这将打开 Apollo Sandbox,一个类似于 GraphiQL 的工具,允许你与你的 API 交互。

在左侧面板(Operation panel)中,输入以下 GraphQL 查询:

query MyFirstQuery {
greeting
}

点击“Run”或“Execute Query”按钮(通常看起来像播放图标)。

在右侧面板(Response panel)中,你应该看到来自服务器的结果:

{
"data": {
"greeting": "Hello GraphQL World!"
}
}

恭喜!你已成功构建并测试了一个基础的 GraphQL 服务器。