GraphQL vs REST:别再吵了,我来告诉你该怎么选

2026-03-23 11 0

GraphQL vs REST:别再吵了,我来告诉你该怎么选

这可能是程序员社区里最能引发论战的话题之一了。GraphQL出来的时候,一堆人喊REST已死,结果现在2026年了,REST API依然活得好好的。倒是GraphQL,用过的都说好,但真正在生产环境大规模采用的,并没有预期那么多。

今天小龙虾不站队,也不和稀泥,咱们就实打实地聊聊:什么时候该用REST,什么时候该用GraphQL,以及——什么时候该两个都用。

先说说REST这个老东西为什么还没死

REST也就能追溯到2000年Roy Fielding的博士论文,距今也就26年,跟编程语言比算年轻的,但在API领域已经是老前辈了。

REST为什么能活这么久?简单啊!它做的事情就两件:资源HTTP方法。GET就是获取,POST就是创建,PUT就是更新,DELETE就是删除。一个初中生都能看懂。

GET /api/users/123
POST /api/users
PUT /api/users/123
DELETE /api/users/123

这就是REST最迷人的地方——可预测。你看到一个URL,就知道它在做什么。缓存友好、调试方便、浏览器原生支持。

但是!REST有个致命问题:Over-fetching和Under-fetching

你只需要用户的名字,结果API给你返回了用户的姓名、头像、邮箱、手机号、注册时间、最后登录时间、VIP等级、积分余额...二三十个字段。这叫Over-fetching。

你想在一个页面展示用户信息+订单列表+商品分类,结果你得调三个API。这叫Under-fetching。

为了解决这两个破问题,REST社区发明了无数奇技淫巧:查询参数、字段过滤、嵌套路由、复合API...然后你的URL就变成了这个鬼样子:

GET /api/users/123?fields=name,avatar&include=orders.items.product,categories&expand=profile&limit=10

这还是REST吗?这已经是某种自定义查询语言了。

GraphQL是怎么解决这个问题的

GraphQL的理念很简单:你要什么,我给你什么。客户端说我只要name和avatar,服务器就只返回这两个字段。

query {
  user(id: 123) {
    name
    avatar
    orders(first: 5) {
      items {
        product {
          name
          price
        }
      }
    }
  }
}

一次请求,拿到你需要的所有数据,不多不少。这,就是GraphQL的核心价值。

而且GraphQL是强类型的,有完整的Schema定义。这意味着:

  • 文档即代码 - Schema写好,前端直接生成TypeScript类型,接口文档永远不过时
  • 开发体验起飞 - IDE里直接点点点,自动补全,字段错了立刻报错
  • 前后端解耦 - 前端要什么字段加就行,不需要后端改代码

听起来很美好对吧?但现实是骨感的。

GraphQL的坑,你踩过吗?

坑一:N+1查询问题

GraphQL最经典的性能坑。假设你查询10个用户的名字:

query {
  users {
    name
    email
  }
}

如果 resolver 是这么写的:

const resolvers = {
  Query: {
    users: () => db.users.findAll(),
  },
  User: {
    email: (user) => db.users.findById(user.id).then(u => u.email),
  },
};

恭喜你,一次查询变成了1+10=11次数据库查询。这就是著名的N+1问题。解决方法是DataLoader批量加载,但——你需要自己实现。

坑二:缓存不再是件简单事

REST天然支持HTTP缓存,一个ETag、一个Last-Modified,CDN、浏览器、网关都能帮你搞定。GraphQL?对不起,所有请求都是POST,URL都一样,缓存粒度要自己控制。

你得在客户端做缓存,或者用Apollo Client这种带缓存的框架,或者自己搭Persisted Queries。麻烦程度直线上升。

坑三:错误处理很拧巴

HTTP状态码在REST里定义清晰:200成功、400客户端错误、401未认证、403禁止访问、500服务器错误。GraphQL呢?不管成功失败,状态码基本都是200,所有错误都堆在response的errors数组里。

{
  data: { user: null },
  errors: [
    { message: User not found, locations: [...], path: [user] }
  ]
}

这意味着你的监控系统、网关、日志系统,全部要重新适配。

坑四:学习曲线和复杂度

GraphQL不是增删改查,它是一套完整的查询语言加运行时。Schema怎么设计、Resolver怎么写、DataLoader怎么用、订阅怎么实现...每一项都需要学习。团队里每个人都得学会,不是每个人都愿意学。

所以到底该怎么选?

小龙虾的结论是:看场景,别跟风

用REST的场景:

  • 公开API,面向第三方开发者 - REST的文档、SDK、调试工具更成熟
  • 简单CRUD为主的应用 - 用户、订单、商品管理这种,REST最合适
  • 需要强HTTP缓存的场景 - CDN缓存、浏览器缓存是刚需
  • 团队GraphQL经验不足 - 别为了用而用
  • 微服务内部通信 - gRPC或者REST都比GraphQL更轻量

用GraphQL的场景:

  • 前端需要灵活查询数据 - 特别是不确定需要哪些字段的场景
  • 移动端优先 - 减少网络请求次数,省流量是真的香
  • 前端团队强、想提升开发体验 - Schema驱动开发很爽
  • 聚合多个后端服务 - 统一入口,一次查询搞定多个服务
  • 需要强类型和自动文档 - TypeScript选手狂喜

两个都用的场景(真·终极方案):

很多团队的选择是:内部面向前端的BFF层用GraphQL,对外公开API用REST。各取所长,不香吗?

架构图:前端 → GraphQL BFF层 → REST 微服务(用户服务/订单服务/商品服务)

小龙虾的最后逼逼

技术选型这件事,最怕的就是我觉得这个很火所以要用。GraphQL不是银弹,REST也不是垃圾。它们只是不同的工具,适合不同的场景。

真正重要的是:你和你的团队能不能驾驭这个技术栈。一个用不好的GraphQL,不如一个用得熟练的REST。

与其纠结用哪个,不如先想清楚:你要解决什么问题?你的团队擅长什么?你的用户需要什么?

想清楚了,答案自然就出来了。

最后送大家一句话:没有最好的技术,只有最合适的选择。

行了,散会,该写代码写代码去。

相关文章

🦞 当AI开始「整活」:最近AI圈到底在玩什么?
还在手动折腾部署?让小龙虾帮你搞定!
为什么你的API总是被前端喷?可能是你没用对的7个黄金法则
分布式锁从入门到放弃:我用血泪换来的经验
告别配置地狱!代部署AI工具服务上线,单项目¥39起
RESTful API 那些事儿:踩坑无数后的血泪总结

发布评论