一名开发者花了两个星期,将内部工具中的 REST API 替换成了 tRPC。
为什么这次切换至关重要
旧的技术栈迫使我们必须维护 DTO、校验器以及一套独立的用于前端的 TypeScript 类型。只要重命名一个后端字段,API 仍会返回 200,UI 会继续渲染,而 bug 最终只会以 “undefined” 值的形式出现。在团队成员发现问题之前,客户就已经发现了。REST 契约掩盖了问题,而额外的文件增加了维护成本,却从未带来回报。
原有的 REST 配置是怎样的
- OpenAPI spec – 一个描述端点的静态文件,但从未充当过事实来源(source of truth)。
- Client SDK generation step – 一个生成 JavaScript 包装器的 CI 任务。
- Postman collection – 一个无人使用的共享测试产物。
- Manual TypeScript interfaces – 必须与服务器保持同步的手写类型。
每次 API 变更都会影响其中至少三个产物,此外还要修改校验器和任何下游的 fetch 调用。这个过程既容易出错又缓慢。
tRPC 如何精简了代码库
tRPC 消除了独立的契约文件。服务器导出 router 类型,客户端导入同一个类型。重命名一个后端字段,编辑器会立即标记不匹配之处——无需运行代码,也无需等待请求失败。开发者删除了:
- OpenAPI spec 文件。
- Client SDK 生成步骤。
- 不再使用的 Postman collection。
- 手写 TypeScript 接口的文件夹。
代码库变得更加精简,反馈在开发阶段就能得到,而不是在部署之后。
tRPC 的局限性
只有当两端都使用 TypeScript 时,tRPC 才能发挥作用。在以下情况下它并不适用:
- 移动端团队使用 Swift 或 Kotlin。
- API 必须由外部合作伙伴调用。
- 你需要一个公开的、与语言无关的接口。
迁移实际需要做些什么
这两周的工作不仅仅是复制粘贴。开发者必须:
- 重写每一个
fetch调用,改用 tRPC 的客户端函数。 - 调整错误处理逻辑。
- 更新依赖于原始 HTTP 响应的加载和重试状态的 UI 组件。
决策前需要思考的问题
- 前端和后端都使用 TypeScript 吗? 如果没有共享的类型系统,tRPC 就会失去其核心优势。
- 双方是否由同一个团队负责? 权责划分不清可能会重新导致契约漂移(contract drift)。
- 你是在修复具体的 bug,还是在追逐潮流? 生产力的提升是真实的,但它应该用来解决现有的痛点。
2025 年的混合方案
许多团队通过同时运行这两套技术栈找到了平衡点:
- tRPC 用于内部应用层,即代码库完全使用 TypeScript,且由同一个团队负责服务器和客户端。
- REST 用于 Webhooks、公开 API 和合作伙伴集成,即需要与语言无关的访问方式。
为每个层面选择合适的工具,既能保持内部开发的快速,又能保留外部消费者所需的开放性。
总结: 将 REST 替换为 tRPC 可以消除重复的契约产物,并在编辑时暴露 bug,但只有当整个技术栈共享 TypeScript 且团队能够承担迁移成本时,这些收益才会真正实现。混合策略让你在享受收益的同时,不会将非 TypeScript 的消费者拒之门外。
