GraphQL是一种用于API的查询语言,由Facebook开发。它提供了一种更高效、强大和灵活的方式来获取数据,让客户端精确指定需要的数据。
定义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! }
客户端按需获取数据。
query GetUser { user(id: "1") { name email posts { title } } }
修改数据。
mutation CreatePost { createPost( title: "GraphQL入门" content: "这是一篇关于GraphQL的文章" authorId: "1" ) { id title } }
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}`); });
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'));
使用游标分页或偏移分页。
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 }
实时数据推送。
type Subscription { postCreated: Post! } const resolvers = { Subscription: { postCreated: { subscribe: (parent, args, { pubsub }) => { return pubsub.asyncIterator(['POST_CREATED']); } } } };
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'); } }; } } ] });
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 } ); } } } };
使用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); } } };
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); } } };
const { createComplexityLimitRule } = require('graphql-validation-complexity'); const server = new ApolloServer({ validationRules: [ createComplexityLimitRule(1000) ] });
const { ApolloServer } = require('apollo-server'); const { persistQueries } = require('@graphql-tools/persisted-queries'); const server = new ApolloServer({ persistedQueries: { ttl: 900 } });
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') } });
GraphQL管理和监控平台。
交互式IDE,用于测试查询。
从schema自动生成类型。
统一配置工具。
GraphQL提供了:
适合场景:
但也需要考虑:
GraphQL不是REST的替代品,而是另一种API设计选择。根据项目需求选择合适的方案。