别再问“谁更好”,先问“场景是什么”
REST 和 GraphQL 之争在网上吵了十年,但成熟的工程师都知道:技术选型从来不是非黑即白。REST 是资源导向的 HTTP 接口约定,GraphQL 是一套查询语言 + 运行时。它们解决的核心问题都是“前后端如何交换数据”,但代价和收益截然不同。
本文从多个工程维度做一次冷静对比,并给出 2026 年的选型建议。
数据获取:过取与欠取
REST 最大的痛点是“端点固定、返回固定”。一个文章详情页可能需要:文章本体、作者信息、评论列表。REST 常见做法是三个端点,前端发三次请求;或者后端专门做一个聚合端点 /articles/{id}/full,结果移动端只需要标题,又取回了一堆冗余字段。
# 前端精确声明需要的字段
query ArticleDetail($id: ID!) {
article(id: $id) {
title
author {
name
avatar
}
comments(last: 5) {
content
createdAt
}
}
}一次请求拿到所有数据,且没有多余字段。这是 GraphQL 最具说服力的优势。
REST 依然不可替代的地方
但 REST 并非没有还手之力,它在以下场景仍然更优:
ETag、Cache-Control、CDN 缓存开箱即用。GraphQL 默认是单个 POST 端点,缓存要靠 Apollo Client 的 normalized cache 或 Persisted Query,复杂度高得多。版本管理
REST 的版本管理是个老大难:/v1/users 还是 /v2/users?多个版本长期共存让维护成本飙升。
GraphQL 通过 Schema 演进优雅地解决这个问题:新增字段不影响旧客户端;废弃字段标记 @deprecated,客户端有充裕时间迁移;真正要破坏性变更时才考虑版本。
type User {
id: ID!
name: String!
fullName: String @deprecated(reason: "Use `name` instead.")
}类型系统与前端体验
GraphQL 的 Schema 就是强类型契约。配合代码生成(如 graphql-codegen),前端拿到的请求函数和类型是完全同步的,TS 项目体验极佳。
// codegen 自动生成
export type ArticleQuery = {
article: {
__typename: "Article";
title: string;
author: { __typename: "Author"; name: string };
} | null;
};REST 也能用 OpenAPI 规范 + 代码生成达到类似效果,但需要额外维护 Swagger 文档并保证与代码同步,实践中常常脱节。
N+1 与性能陷阱
GraphQL 的灵活性也是它的“坑”。前端可以嵌套查询 user -> posts -> comments -> author,一条查询可能触发数据库 N+1 问题,瞬间拖垮后端。
解决之道是 DataLoader:在单次请求内批量加载、去重、缓存关联数据。
const { DataLoader } = require("@apollo/server");
const userLoader = new DataLoader(async (userIds) => {
// 一次性查出所有 user,按顺序返回
const users = await db.users.findMany({ id: { in: userIds } });
return userIds.map((id) => users.find((u) => u.id === id));
});
const resolvers = {
Comment: {
author: (comment) => userLoader.load(comment.authorId),
},
};此外还要给查询设置深度限制和复杂度限制,防止恶意嵌套查询打爆服务器。
import depthLimit from "graphql-depth-limit";
const server = new ApolloServer({
typeDefs,
resolvers,
validationRules: [depthLimit(5)],
});鉴权与错误处理
errors 数组里。鉴权在 resolver 层按字段粒度做,更灵活但也更易出错。const resolvers = {
Query: {
me: (_, __, { user }) => {
if (!user) throw new GraphQLError("未登录", { extensions: { code: "UNAUTHENTICATED" } });
return user;
},
},
};2026 年的选型建议
结合实际工程经验,给出如下决策参考:
| 场景 | 推荐 | 理由 |
| --- | --- | --- |
| 移动端为主、流量敏感 | GraphQL | 精准取字段,省流量、省请求 |
| 多端共用一套 API(Web/App/小程序) | GraphQL | 一处 Schema,多端按需取数 |
| 对外开放 API、第三方集成 | REST | 标准、可缓存、网关治理简单 |
| 内部微服务间通信 | REST / gRPC | 简单直接、性能优先 |
| 复杂聚合、关系型数据展示 | GraphQL | 避免多次往返 |
| 简单 CRUD 后台 | REST | 上手快、维护成本低 |
一个越来越常见的折中方案是 BFF(Backend for Frontend)+ GraphQL 网关:底层微服务用 REST/gRPC,面向前端的聚合层用 GraphQL,既保留了微服务的简洁,又给前端提供了灵活查询能力。
渐进式迁移
很多团队担心“已有大量 REST 接口,怎么上 GraphQL”。其实可以共存:
class UsersAPI extends RESTDataSource {
baseURL = "https://api.internal/v1/";
async getUser(id) {
return this.get(`users/${id}`);
}
}小结
GraphQL 不是 REST 的替代品,而是补充。GraphQL 赢在数据获取灵活性和类型契约,REST 赢在缓存、治理和简单性。选型的核心是看你的前端是否真有“多端、多变、按需取数”的痛点。如果答案是肯定的,GraphQL 会让前端开发体验上一个台阶;如果只是简单的资源 CRUD,REST 依旧是性价比最高的选择。成熟架构里,两者共存、各司其职,才是 2026 年的常态。
💬 评论区 (0)
暂无评论,快来抢沙发吧!