GraphQL
概述
GraphQL 是 API 查询语言,客户端可以精确获取所需数据。
一、GraphQL vs REST
| 特性 | GraphQL | REST |
|---|---|---|
| 端点 | 单一 | 多个 |
| 数据获取 | 精确字段 | 固定结构 |
| 版本控制 | 演进式 | v1/v2/v3 |
| Over-fetching | 无 | 常见 |
| Under-fetching | 无 | 常见 |
二、基础查询
graphql
# 查询
query GetUser($id: ID!) {
user(id: $id) {
id
name
posts {
title
}
}
}
# 变更
mutation CreatePost($input: PostInput!) {
createPost(input: $input) {
id
title
}
}
# 订阅
subscription OnPostCreated {
postCreated {
id
title
}
}三、Apollo Client
javascript
import { ApolloClient, InMemoryCache, gql, useQuery } from '@apollo/client';
const client = new ApolloClient({
uri: 'https://api.example.com/graphql',
cache: new InMemoryCache()
});
// React Hook
const GET_USERS = gql`
query GetUsers {
users { id name }
}
`;
function Users() {
const { loading, error, data } = useQuery(GET_USERS);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
return data.users.map(user => <div key={user.id}>{user.name}</div>);
}四、缓存与优化
javascript
// 缓存更新
const [createPost] = useMutation(CREATE_POST, {
update(cache, { data: { createPost } }) {
const { posts } = cache.readQuery({ query: GET_POSTS });
cache.writeQuery({
query: GET_POSTS,
data: { posts: [...posts, createPost] }
});
}
});
// 乐观更新
const [updatePost] = useMutation(UPDATE_POST, {
optimisticResponse: {
updatePost: { id: '1', title: 'New Title', __typename: 'Post' }
}
});五、分页
graphql
# Cursor-based
query GetPosts($first: Int!, $after: String) {
posts(first: $first, after: $after) {
edges {
node { id title }
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}面试高频题
Q1: GraphQL 优势?
精确数据获取、单一端点、强类型、自文档化。
Q2: N+1 问题?
多层嵌套查询导致多次数据库查询,使用 DataLoader 批量加载解决。
Q3: 缓存策略?
Apollo 使用 normalized cache,按 id + __typename 缓存实体。