API 集成入门:REST vs GraphQL 对比与选型指南
无论你是前端开发者还是后端开发者,API 都是日常工作中不可或缺的部分。REST 多年来一直是 API 设计的标准,而 GraphQL 作为一种更灵活的新范式正在快速普及。
一、REST 基础
1.1 什么是 REST
REST(Representational State Transfer)是一种基于 HTTP 协议的 API 设计风格。核心思想是将资源抽象为 URL,通过 HTTP 方法进行操作。
# RESTful API 设计
GET /api/users # 获取用户列表
GET /api/users/1 # 获取单个用户
POST /api/users # 创建用户
PUT /api/users/1 # 更新用户
DELETE /api/users/1 # 删除用户
1.2 REST 请求示例
// 获取用户及其文章
const user = await fetch('/api/users/1').then(r => r.json());
const posts = await fetch('/api/users/1/posts').then(r => r.json());
const comments = await fetch('/api/posts/1/comments').then(r => r.json());
// 响应通常包含固定结构
// GET /api/users/1
{
"id": 1,
"name": "张三",
"email": "[email protected]",
"avatar": "https://..."
}
二、GraphQL 基础
2.1 什么是 GraphQL
GraphQL 是由 Facebook 开发的一种 API 查询语言。客户端可以精确指定需要的数据,不多不少。
# GraphQL 查询
query {
user(id: 1) {
name
email
posts {
title
comments {
content
author {
name
}
}
}
}
}
2.2 GraphQL 响应
{
"data": {
"user": {
"name": "张三",
"email": "[email protected]",
"posts": [
{
"title": "第一篇文章",
"comments": [
{
"content": "写得好!",
"author": {
"name": "李四"
}
}
]
}
]
}
}
}
三、核心差异对比
3.1 数据获取
| 维度 | REST | GraphQL |
|---|---|---|
| 数据量 | 固定结构,可能过多或不足 | 客户端精确指定 |
| 请求次数 | 可能需要多次请求 | 一次请求获取所有数据 |
| 嵌套数据 | 需多次请求或自定义端点 | 直接在查询中嵌套 |
3.2 示例对比
场景:获取用户信息 + 最新的 5 篇文章 + 每篇文章的前 3 条评论
REST 方式:
// 3 次 API 请求
const user = await fetch('/api/users/1');
const posts = await fetch('/api/users/1/posts?limit=5');
const comments = await Promise.all(
posts.map(p => fetch(`/api/posts/${p.id}/comments?limit=3`))
);
// 或者后端专门创建一个聚合端点
GraphQL 方式:
query {
user(id: 1) {
name
email
posts(last: 5) {
title
comments(last: 3) {
content
author { name }
}
}
}
}
// 一次请求获得所有数据
3.3 性能对比
| 特性 | REST | GraphQL |
|---|---|---|
| 缓存 | HTTP 缓存天然支持 | 需要额外缓存方案 |
| 网络请求数 | 可能较多 | 通常较少 |
| 载荷大小 | 可能包含不需要的数据 | 客户端精确指定 |
| 服务器性能 | 可控(预定义的数据集) | 需防范复杂查询 |
四、服务端实现
REST 实现(Node.js + Express)
// REST 路由
const express = require('express');
const app = express();
app.get('/api/users/:id', async (req, res) => {
const user = await db.findUser(req.params.id);
res.json(user);
});
app.get('/api/users/:id/posts', async (req, res) => {
const posts = await db.findPostsByUser(req.params.id);
res.json(posts);
});
GraphQL 实现(Node.js + Apollo Server)
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!
comments: [Comment!]!
}
type Query {
user(id: ID!): User
}
`;
// 解析器
const resolvers = {
Query: {
user: async (_, { id }) => db.findUser(id),
},
User: {
posts: async (user) => db.findPostsByUser(user.id),
},
};
const server = new ApolloServer({ typeDefs, resolvers });
server.listen(4000);
五、选型建议
选 REST 的场景
- 简单 CRUD 应用:数据模型简单,不需要嵌套查询
- 缓存是关键需求:REST 的 HTTP 缓存机制成熟
- 微服务架构:服务间 REST 接口更加直观
- 文件上传/下载:处理二进制数据更自然
- 团队对 REST 更熟悉:降低学习成本
选 GraphQL 的场景
- 复杂的前端数据需求:不同页面需要不同数据集
- 多个前端客户端:Web + Mobile 需要不同数据
- API 需要快速迭代:前端需求变更时后端不需要改接口
- 数据有复杂的嵌套关系:一次查询获取关联数据
六、混合方案
很多团队采用 REST + GraphQL 混合方案:
方案一:GraphQL 作为 API Gateway
GraphQL Gateway → REST 服务 A / REST 服务 B / REST 服务 C
前端只与 GraphQL 交互,后端服务之间用 REST
方案二:一部分用 REST,一部分用 GraphQL
公开 API → REST(缓存友好)
内部前端 → GraphQL(灵活取数)
七、总结
REST 和 GraphQL 不是非此即彼的选择。REST 胜在简洁、缓存友好和生态成熟;GraphQL 胜在灵活、高效和类型安全。对于新项目,可以考虑从 GraphQL 开始(特别是前后端分离的 SPA 应用);对于已有 REST API,可以逐步引入 GraphQL,没有迁移压力。技术选型的核心是匹配业务需求,而不是追逐热门技术。