前端 GraphQL:别让 REST API 限制你的数据获取
前端 GraphQL别让 REST API 限制你的数据获取什么是 GraphQLGraphQL 是一种用于 API 的查询语言也是一个满足你数据查询的运行时。别以为 GraphQL 只是个时髦的新技术它解决了 REST API 的许多痛点让前端开发者能够更灵活地获取数据。为什么需要 GraphQL精确获取数据只获取需要的数据避免过度获取或获取不足减少网络请求一次请求获取多个资源减少网络延迟类型安全强类型系统提供更好的开发体验和错误检查自我描述API 本身包含类型定义和文档实时数据支持订阅Subscription实现实时数据更新GraphQL 核心概念1. 查询Query查询是客户端获取数据的主要方式类似于 REST 的 GET 请求。# 查询单个用户 query GetUser { user(id: 1) { id name email posts { title content } } } # 查询多个用户 query GetUsers { users { id name email } }2. 变更Mutation变更用于修改服务器端数据类似于 REST 的 POST、PUT、DELETE 请求。# 创建用户 mutation CreateUser { createUser(input: { name: cannonmonster01 email: cannonmonster01example.com }) { id name email } } # 更新用户 mutation UpdateUser { updateUser(id: 1, input: { name: cannonmonster02 }) { id name email } } # 删除用户 mutation DeleteUser { deleteUser(id: 1) { id } }3. 订阅Subscription订阅用于获取实时更新当服务器端数据发生变化时客户端会收到通知。# 订阅用户更新 subscription UserUpdated { userUpdated(id: 1) { id name email } }4. 类型Type类型定义了 API 的数据结构包括对象类型、标量类型、枚举类型等。# 定义用户类型 type User { id: ID! name: String! email: String! posts: [Post!]! } # 定义帖子类型 type Post { id: ID! title: String! content: String! author: User! createdAt: DateTime! } # 定义查询类型 type Query { user(id: ID!): User users: [User!]! post(id: ID!): Post posts: [Post!]! } # 定义变更类型 type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! deleteUser(id: ID!): User! createPost(input: CreatePostInput!): Post! updatePost(id: ID!, input: UpdatePostInput!): Post! deletePost(id: ID!): Post! } # 定义输入类型 input CreateUserInput { name: String! email: String! } input UpdateUserInput { name: String email: String } # 定义订阅类型 type Subscription { userUpdated(id: ID!): User! postCreated: Post! }GraphQL 客户端1. Apollo ClientApollo Client 是最流行的 GraphQL 客户端库支持 React、Vue、Angular 等框架。// 安装 // npm install apollo/client graphql // 配置 import { ApolloClient, InMemoryCache, gql } from apollo/client; const client new ApolloClient({ uri: https://api.example.com/graphql, cache: new InMemoryCache() }); // 执行查询 const GET_USERS gql query GetUsers { users { id name email } } ; client.query({ query: GET_USERS }).then(result { console.log(result.data.users); }); // 在 React 中使用 import { useQuery } from apollo/client; function UsersList() { const { loading, error, data } useQuery(GET_USERS); if (loading) return pLoading.../p; if (error) return pError: {error.message}/p; return ( ul {data.users.map(user ( li key{user.id} {user.name} ({user.email}) /li ))} /ul ); }2. RelayRelay 是 Facebook 开发的 GraphQL 客户端库专为 React 优化。// 安装 // npm install relay-runtime react-relay // 配置 import { Environment, Network, RecordSource, Store } from relay-runtime; function fetchQuery(operation, variables) { return fetch(https://api.example.com/graphql, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify({ query: operation.text, variables, }), }).then(response { return response.json(); }); } const environment new Environment({ network: Network.create(fetchQuery), store: new Store(new RecordSource()), }); // 在 React 中使用 import { useLazyLoadQuery, graphql } from react-relay; const GET_USERS graphql query UsersListQuery { users { id name email } } ; function UsersList() { const data useLazyLoadQuery( GET_USERS, {} ); return ( ul {data.users.map(user ( li key{user.id} {user.name} ({user.email}) /li ))} /ul ); }3. urqlurql 是一个轻量级的 GraphQL 客户端库支持 React、Vue、Svelte 等框架。// 安装 // npm install urql graphql // 配置 import { createClient, gql } from urql; const client createClient({ url: https://api.example.com/graphql, }); // 执行查询 const GET_USERS gql query GetUsers { users { id name email } } ; client.query(GET_USERS).toPromise().then(result { console.log(result.data.users); }); // 在 React 中使用 import { useQuery } from urql; function UsersList() { const [result] useQuery({ query: GET_USERS, }); const { data, fetching, error } result; if (fetching) return pLoading.../p; if (error) return pError: {error.message}/p; return ( ul {data.users.map(user ( li key{user.id} {user.name} ({user.email}) /li ))} /ul ); }GraphQL 服务端1. Apollo ServerApollo Server 是最流行的 GraphQL 服务器库支持 Node.js、Python、Java 等语言。// 安装 // npm install apollo-server graphql // 配置 const { ApolloServer, gql } require(apollo-server); // 定义类型 const typeDefs gql type User { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! createdAt: String! } type Query { user(id: ID!): User users: [User!]! post(id: ID!): Post posts: [Post!]! } type Mutation { createUser(name: String!, email: String!): User! updateUser(id: ID!, name: String, email: String): User! deleteUser(id: ID!): User! createPost(title: String!, content: String!, authorId: ID!): Post! updatePost(id: ID!, title: String, content: String): Post! deletePost(id: ID!): Post! } ; // 模拟数据 let users [ { id: 1, name: cannonmonster01, email: cannonmonster01example.com }, { id: 2, name: user2, email: user2example.com } ]; let posts [ { id: 1, title: GraphQL 入门, content: GraphQL 是一种查询语言, authorId: 1, createdAt: new Date().toISOString() }, { id: 2, title: React 最佳实践, content: React 开发的最佳实践, authorId: 1, createdAt: new Date().toISOString() } ]; // 定义解析器 const resolvers { Query: { user: (_, { id }) users.find(user user.id id), users: () users, post: (_, { id }) posts.find(post post.id id), posts: () posts }, Mutation: { createUser: (_, { name, email }) { const newUser { id: String(users.length 1), name, email }; users.push(newUser); return newUser; }, updateUser: (_, { id, name, email }) { const user users.find(user user.id id); if (name) user.name name; if (email) user.email email; return user; }, deleteUser: (_, { id }) { const user users.find(user user.id id); users users.filter(user user.id ! id); return user; }, createPost: (_, { title, content, authorId }) { const newPost { id: String(posts.length 1), title, content, authorId, createdAt: new Date().toISOString() }; posts.push(newPost); return newPost; }, updatePost: (_, { id, title, content }) { const post posts.find(post post.id id); if (title) post.title title; if (content) post.content content; return post; }, deletePost: (_, { id }) { const post posts.find(post post.id id); posts posts.filter(post post.id ! id); return post; } }, User: { posts: (user) posts.filter(post post.authorId user.id) }, Post: { author: (post) users.find(user user.id post.authorId) } }; // 创建服务器 const server new ApolloServer({ typeDefs, resolvers }); // 启动服务器 server.listen().then(({ url }) { console.log(Server ready at ${url}); });2. Express GraphQLExpress GraphQL 是一个基于 Express 的 GraphQL 服务器库。// 安装 // npm install express express-graphql graphql // 配置 const express require(express); const { graphqlHTTP } require(express-graphql); const { buildSchema } require(graphql); // 定义 schema const schema buildSchema( type User { id: ID! name: String! email: String! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! createdAt: String! } type Query { user(id: ID!): User users: [User!]! post(id: ID!): Post posts: [Post!]! } type Mutation { createUser(name: String!, email: String!): User! updateUser(id: ID!, name: String, email: String): User! deleteUser(id: ID!): User! createPost(title: String!, content: String!, authorId: ID!): Post! updatePost(id: ID!, title: String, content: String): Post! deletePost(id: ID!): Post! } ); // 模拟数据 let users [ { id: 1, name: cannonmonster01, email: cannonmonster01example.com }, { id: 2, name: user2, email: user2example.com } ]; let posts [ { id: 1, title: GraphQL 入门, content: GraphQL 是一种查询语言, authorId: 1, createdAt: new Date().toISOString() }, { id: 2, title: React 最佳实践, content: React 开发的最佳实践, authorId: 1, createdAt: new Date().toISOString() } ]; // 定义根解析器 const root { user: ({ id }) users.find(user user.id id), users: () users, post: ({ id }) posts.find(post post.id id), posts: () posts, createUser: ({ name, email }) { const newUser { id: String(users.length 1), name, email }; users.push(newUser); return newUser; }, updateUser: ({ id, name, email }) { const user users.find(user user.id id); if (name) user.name name; if (email) user.email email; return user; }, deleteUser: ({ id }) { const user users.find(user user.id id); users users.filter(user user.id ! id); return user; }, createPost: ({ title, content, authorId }) { const newPost { id: String(posts.length 1), title, content, authorId, createdAt: new Date().toISOString() }; posts.push(newPost); return newPost; }, updatePost: ({ id, title, content }) { const post posts.find(post post.id id); if (title) post.title title; if (content) post.content content; return post; }, deletePost: ({ id }) { const post posts.find(post post.id id); posts posts.filter(post post.id ! id); return post; } }; // 创建 Express 应用 const app express(); // 添加 GraphQL 端点 app.use(/graphql, graphqlHTTP({ schema: schema, rootValue: root, graphiql: true // 启用 GraphiQL 界面 })); // 启动服务器 app.listen(4000, () { console.log(Server running at http://localhost:4000/graphql); });GraphQL 最佳实践使用碎片Fragments重用查询片段减少代码重复分页对大型数据集使用分页避免一次性获取过多数据缓存使用客户端缓存减少重复请求批量处理使用批量处理减少网络请求错误处理实现统一的错误处理机制权限控制在服务器端实现权限控制性能监控监控查询性能优化慢查询GraphQL 案例1. GitHub APIGitHub API v4 使用 GraphQL提供了更灵活的数据获取方式。2. Shopify APIShopify API 使用 GraphQL允许开发者精确获取所需的数据。3. Facebook APIFacebook API 使用 GraphQL提供了高效的数据获取方式。总结GraphQL 是一种现代化的 API 技术它解决了 REST API 的许多痛点让前端开发者能够更灵活地获取数据。别让 REST API 限制你的数据获取赶紧拥抱 GraphQL 吧记住GraphQL 不是银弹它适用于复杂的 API 场景。对于简单的 APIREST 可能仍然是更好的选择。选择合适的 API 设计方案根据实际需求进行权衡才能构建出高质量的前端应用。