GraphQL vs REST:从 7 个维度深度对比

Choyeon· 2026年9月19日· 3 分钟阅读· 222 阅读· 710 字· 2,123 字符· 更新于 2026年10月1日
GraphQL vs REST:从 7 个维度深度对比

GraphQL 常被宣传为 REST 的终结者,但实际两者各有适合场景。盲目选择 GraphQL 会带来 N+1 查询、复杂度爆炸、缓存失效等坑;只用 REST 又有过取/欠取问题。理性对比再做选择。

典型架构与复杂度防护

GraphQL 单端点接收查询,前端声明式指定字段结构,解决 REST 常见的 20 个接口拼数据或大接口返回 80% 不用字段的问题。但必须在网关层加上查询复杂度分析、字段级权限、深度限制。

import express, { Request, Response } from "express";
import { graphqlHTTP } from "express-graphql";
import { buildSchema, parse, visit, Kind } from "graphql";

const app = express();
app.use(express.json());

const schema = buildSchema(`
  type User { id: ID!; username: String!; orders(limit: Int = 10): [Order!]! }
  type Order { id: ID!; total: Float!; items(limit: Int = 20): [OrderItem!]! }
  type OrderItem { productId: ID!; qty: Int!; price: Float! }
  type Query { user(id: ID!): User; users(limit: Int = 20): [User!]! }
  schema { query: Query }
`);

class ComplexityGuard {
    private costs: Record<string, number> = { orders: 5, items: 2, users: 10 };
    private readonly MAX = 150;
    analyze(query: string): { total: number; exceeded: boolean } {
        const doc = parse(query); let total = 1;
        visit(doc, {
            Field: (node) => {
                const base = this.costs[node.name.value] || 1;
                const args = Object.fromEntries((node.arguments || []).map(a => [a.name.value, (a.value as any).value]));
                const mult = args.limit ? Math.ceil(Number(args.limit) / 10) : 1;
                total += base * mult;
            },
        });
        return { total, exceeded: total > this.MAX };
    }
}

const root = {
    user: ({ id }: { id: string }) => ({
        id, username: `u${id}`,
        orders: ({ limit = 10 }: any) => Array.from({ length: limit }, (_, i) => ({
            id: `o${i}`, total: 99.5 + i,
            items: ({ limit = 20 }: any) => Array.from({ length: limit }, (_, k) => ({ productId: `p${k}`, qty: k + 1, price: 9.9 })),
        })),
    }),
    users: ({ limit = 20 }: any) => Array.from({ length: limit }, (_, i) => root.user({ id: String(i + 1) })),
};

const guard = new ComplexityGuard();
app.get("/rest/users/:id", (req: Request, res: Response) => {
    res.json({ data: { id: req.params.id, username: `u${req.params.id}` }, _links: { orders: { href: `/rest/users/${req.params.id}/orders` } } });
});
app.use("/graphql", (req: Request, res: Response, next) => {
    const q = (req.body?.query) || (req.query.query as string) || "";
    const r = guard.analyze(q);
    if (r.exceeded) return res.status(400).json({ error: `Complexity ${r.total} exceeds cap 150` });
    res.setHeader("X-GraphQL-Complexity", String(r.total));
    next();
}, graphqlHTTP({ schema, rootValue: root, graphiql: process.env.NODE_ENV !== "production" }));

app.listen(3000, () => console.log("[compare] REST+GraphQL on :3000"));

七大维度横向对比

对比维度 REST (JSON:API风格) GraphQL 胜者
网络传输效率 多请求过取欠取 单请求精确字段POST不利CDN 简单REST赢/复杂视图GraphQL赢
前端开发体验 新字段等后端加接口 自助取字段+内省生成类型 GraphQL
后端演进成本 版本化管理/v1/v2 字段弃用平滑但resolver复杂度涨 REST
HTTP缓存 天然支持Get请求 需持久化查询ID+自定义层 REST
类型安全 需OpenAPI代码生成 Schema强类型+内省生成SDK GraphQL
安全风险 普通CRUD鉴权易做 深度/复杂度/批注入要防护 REST安全面更小
生态工具链 OpenAPI/Postman成熟 Apollo Studio/GraphiQL完善 打平

最佳实践

决策树:团队以 BFF 形态存在且前端迭代快 → GraphQL;微服务间调用或纯资源 CRUD → REST;混合架构:BFF 用 GraphQL 组合多个 REST 微服务是目前大厂主流方案。

本文作者

评论 (0)

暂无评论,来抢沙发吧。