GraphQL API设计指南


文档摘要

GraphQL API设计指南 GraphQL概述 GraphQL是一种用于API的查询语言,由Facebook开发。它提供了一种更高效、强大和灵活的方式来获取数据,让客户端精确指定需要的数据。 核心概念 Schema定义 定义API的类型结构和操作。 查询 客户端按需获取数据。 变更 修改数据。 GraphQL vs REST REST的限制 过度获取或获取不足 多个端点 版本管理困难 GraphQL的优势 精确获取需要的数据 单个端点 强类型系统 自描述 实现示例 使用Apollo Server(Node.js) 使用GraphQL Yoga 高级特性 分页 使用游标分页或偏移分页。 订阅 实时数据推送。 中间件 Apollo Server中间件示例。

GraphQL API设计指南

GraphQL概述

GraphQL是一种用于API的查询语言,由Facebook开发。它提供了一种更高效、强大和灵活的方式来获取数据,让客户端精确指定需要的数据。

核心概念

1. Schema定义

定义API的类型结构和操作。

type User { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! } type Query { user(id: ID!): User users: [User!]! post(id: ID!): Post } type Mutation { createUser(name: String!, email: String!): User! createPost(title: String!, content: String!, authorId: ID!): Post! }

2. 查询

客户端按需获取数据。

query GetUser { user(id: "1") { name email posts { title } } }

3. 变更

修改数据。

mutation CreatePost { createPost( title: "GraphQL入门" content: "这是一篇关于GraphQL的文章" authorId: "1" ) { id title } }

GraphQL vs REST

REST的限制

  • 过度获取或获取不足
  • 多个端点
  • 版本管理困难

GraphQL的优势

  • 精确获取需要的数据
  • 单个端点
  • 强类型系统
  • 自描述

实现示例

使用Apollo Server(Node.js)

const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type User { id: ID! name: String! email: String! } type Query { user(id: ID!): User users: [User!]! } `; const resolvers = { Query: { user: (parent, args, context, info) => { return context.db.findUserById(args.id); }, users: (parent, args, context, info) => { return context.db.getAllUsers(); } } }; const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => ({ db: require('./database') }) }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });

使用GraphQL Yoga

const { GraphQLServer } = require('graphql-yoga'); const resolvers = { Query: { user: (parent, { id }, ctx) => { return ctx.db.user({ id }); } } }; const server = new GraphQLServer({ typeDefs: './schema.graphql', resolvers, context: req => ({ ...req, db: new Prisma() }) }); server.start(() => console.log('Server running'));

高级特性

1. 分页

使用游标分页或偏移分页。

type Query { posts(first: Int, after: String): PostConnection! } type PostConnection { edges: [PostEdge!]! pageInfo: PageInfo! } type PostEdge { node: Post! cursor: String! } type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String }

2. 订阅

实时数据推送。

type Subscription { postCreated: Post! } const resolvers = { Subscription: { postCreated: { subscribe: (parent, args, { pubsub }) => { return pubsub.asyncIterator(['POST_CREATED']); } } } };

3. 中间件

Apollo Server中间件示例。

const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => { const token = req.headers.authorization || ''; const user = getUser(token); return { user }; }, plugins: [ { requestDidStart(requestContext) { console.log('Request started'); return { willSendResponse(requestContext) { console.log('Response sent'); } }; } } ] });

最佳实践

1. 错误处理

const resolvers = { Query: { user: async (parent, { id }, { dataSources }) => { try { return await dataSources.userAPI.getUser(id); } catch (error) { throw new ApolloError( 'Failed to fetch user', 'USER_FETCH_FAILED', { id } ); } } } };

2. 数据加载

使用DataLoader解决N+1查询问题。

const DataLoader = require('dataloader'); const userLoader = new DataLoader(async (userIds) => { const users = await db.users.findByIds(userIds); return userIds.map(id => users.find(user => user.id === id)); }); const resolvers = { Post: { author: (post, args, { userLoader }) => { return userLoader.load(post.authorId); } } };

3. 权限控制

const { AuthenticationError, ForbiddenError } = require('apollo-server'); const resolvers = { Mutation: { deletePost: async (parent, { id }, { user, dataSources }) => { if (!user) { throw new AuthenticationError('You must be logged in'); } const post = await dataSources.postAPI.getPost(id); if (post.authorId !== user.id) { throw new ForbiddenError('You are not the author'); } return dataSources.postAPI.deletePost(id); } } };

性能优化

1. 查询复杂度限制

const { createComplexityLimitRule } = require('graphql-validation-complexity'); const server = new ApolloServer({ validationRules: [ createComplexityLimitRule(1000) ] });

2. 查询持久化

const { ApolloServer } = require('apollo-server'); const { persistQueries } = require('@graphql-tools/persisted-queries'); const server = new ApolloServer({ persistedQueries: { ttl: 900 } });

3. 缓存

const { RedisCache } = require('apollo-server-cache-redis'); const server = new ApolloServer({ cache: new RedisCache({ host: 'redis-server', port: 6379 }), responseCachePlugin: { sessionId: (requestContext) => requestContext.request.http.headers.get('session-id') } });

工具生态

1. Apollo Studio

GraphQL管理和监控平台。

2. GraphiQL

交互式IDE,用于测试查询。

3. GraphQL Code Generator

从schema自动生成类型。

4. GraphQL Config

统一配置工具。

总结

GraphQL提供了:

  • 灵活的数据获取
  • 强类型系统
  • 更好的开发体验
  • 减少网络请求

适合场景:

  • 移动应用
  • 复杂的数据关系
  • 需要灵活查询的API

但也需要考虑:

  • 学习曲线
  • 缓存复杂性
  • 安全性配置

GraphQL不是REST的替代品,而是另一种API设计选择。根据项目需求选择合适的方案。


发布者: 作者: 转发
评论区 (0)
U