GraphQL JavaScript库(Node.js):graphql-http
GraphQL是一种由Facebook开发的API查询语言,它允许客户端仅请求他们需要的数据。在Node.js生态系统中,实现GraphQL服务器的关键库之一是graphql-http。这是一个轻量级但功能强大的工具,能够以最小的开销创建高性能API。与Apollo Server等更重量级的解决方案不同,graphql-http提供了灵活性和对HTTP处理程序的完全控制。
什么是graphql-http?
graphql-http是GraphQL社区的官方库,提供了一种将GraphQL连接到任何Node.js HTTP服务器的简单方法。它不依赖于特定框架(Express、Koa、Fastify等),因此是一个通用的选择。该库的主要任务是接收传入的HTTP请求,解析它,执行GraphQL查询,并返回结构化的响应。
安装与配置
首先,通过npm安装该库:
npm install graphql-http graphql纯Node.js(无Express)的最小服务器示例:
const http = require('http');const { createHandler } = require('graphql-http');const { buildSchema } = require('graphql');
// 定义模式const schema = buildSchema(` type Query { hello: String user(id: Int!): User } type User { id: Int name: String email: String }`);
// 解析器const rootValue = { hello: () => '你好,世界!', user: ({ id }) => ({ id, name: `用户 ${id}`, email: `user${id}@example.com` })};
// 创建处理程序const handler = createHandler({ schema, rootValue });
// HTTP服务器const server = http.createServer((req, res) => { if (req.url === '/graphql') { handler(req, res); } else { res.writeHead(404); res.end('Not Found'); }});
server.listen(4000, () => { console.log('服务器已启动于 http://localhost:4000/graphql');});与Express集成
大多数开发者使用Express。graphql-http与Express的集成非常简单:
const express = require('express');const { createHandler } = require('graphql-http');const { buildSchema } = require('graphql');
const schema = buildSchema(` type Query { books: [Book] } type Book { title: String author: String }`);
const books = [ { title: '战争与和平', author: '列夫·托尔斯泰' }, { title: '罪与罚', author: '费奥多尔·陀思妥耶夫斯基' }];
const rootValue = { books: () => books};
const app = express();
app.all('/graphql', createHandler({ schema, rootValue }));
app.listen(3000, () => { console.log('Express + GraphQL 运行于 http://localhost:3000/graphql');});主要功能与优势
- 路由灵活性:您可以自行决定GraphQL在哪个端点可用。
- 支持所有HTTP方法:GET和POST请求都能正确处理。
- 内置验证:库会自动检查请求是否符合模式。
- 高性能:内存占用最小,处理速度快。
- 可扩展性:可以添加用于身份验证、日志记录和缓存的中间件。
处理变更和订阅
除了查询(Query),graphql-http还支持用于修改数据的变更(Mutation)。包含变更的模式示例:
const schema = buildSchema(` type Query { message: String } type Mutation { setMessage(newMessage: String!): String }`);
let message = '旧