tRPC vs GraphQL 对比

零代码生成,端到端 TypeScript 类型安全

VS
GraphQL

模式优先,面向多客户端的通用查询语言

16 分钟阅读Backend

快速结论

要看具体场景,'类型安全'本身不是选择 GraphQL 的理由。如果你只有一个 TypeScript monorepo 加一个 Web 客户端,tRPC 几乎总能带来更少的工作量——零代码生成,服务端一改动客户端立刻报 TS 错误。如果你有移动端应用、需要对外开放的公共 API,或者需要多团队联邦架构,GraphQL 的语言无关模式契约和 Apollo Federation 生态会带来结构性优势。

tRPCGraphQL
阅读完整结论

评分对比

图表加载中…

详细评分

详细评分: tRPC GraphQL ——按类别打分,满分 10 分
分类tRPCGraphQL
性能
7/10
6/10
学习难易度
8/10
5/10
生态系统
6/10
9/10
社区
7/10
8/10
就业市场
5/10
8/10
面向未来
7/10
8/10

优缺点

tRPC

优点

  • 无需代码生成或编译步骤——服务端类型直接流向客户端
  • 服务端一旦修改,客户端在保存文件之前就能看到 TypeScript 错误
  • 为 React、Next.js、Express、Fastify、AWS Lambda、Solid 和 Svelte 提供官方适配器
  • 与 TanStack Query 原生集成——queryKey/queryOptions 工厂开箱即用
  • 根据官方 FAQ,Netflix 和 Pleo 等公司已在生产环境中使用
  • 甚至 TanStack Query 依赖都是可选的——一个简单的原生客户端就足够
  • 支持通过 WebSocket 或 SSE 实现 subscriptions;官方建议 SSE 搭建更简单
  • MIT 许可,完全开源——没有付费企业层

缺点

  • 类型共享依赖同一个 TypeScript monorepo——原生移动端客户端会失去这一优势
  • 没有官方的公开/REST API 层;需要借助 `trpc-to-openapi` 等第三方包
  • 没有模式 introspection——无法向外部开发者提供自描述的契约
  • 没有字段级选择(field selection)——每个过程都有固定的返回类型
  • 无法用于后端不是 JavaScript/TypeScript 的场景
  • 没有官方的联邦/多服务模式组合标准

最适合

单一 TypeScript monorepo + 单一 Web 客户端的产品基于 Next.js、Express 或 Fastify 的全栈 TS 项目需要快速迭代的中小规模团队没有外部消费者的内部工具和管理后台已经在使用 TanStack Query 的项目

GraphQL

优点

  • 客户端只选择自己需要的字段——从结构上解决 over/under-fetching
  • 语言无关的模式契约——原生服务于 iOS、Android、Web 和第三方客户端
  • 通过 introspection 自描述;可通过 GraphiQL 等工具探索
  • 通过弃用(deprecation)机制实现模式演进,无需破坏性变更
  • 官方 `graphql/dataloader` 包通过批处理和缓存解决 N+1 问题
  • Apollo Federation 为多团队/多服务架构提供官方组合方案
  • 自 2018 年起由 Linux Foundation 旗下的 GraphQL Foundation 治理
  • Relay 等官方客户端通过规范化缓存避免不必要的重新渲染

缺点

  • 没有 HTTP 缓存友好的 URL 结构——需要全局 ID + 规范化客户端缓存
  • 模式设计、resolver 架构和 dataloader 等额外概念提高了学习曲线
  • 联邦仍处于标准化过程中——Composite Schema Working Group 仍在积极工作
  • 企业规模下 Apollo GraphOS 等层级需付费(Developer 套餐:每百万请求 5 美元)
  • 不使用 dataloader 会留下 N+1 风险,这是常见的错误类别
  • 在简单 CRUD 场景下,相比 tRPC 或 REST 需要更多样板代码(模式 + resolver)

最适合

面向移动端(iOS/Android)或第三方消费者的 API需要联邦架构的多团队/多服务组织面向外部开发者开放的公共 API查询复杂、嵌套数据图的应用需要企业级 SLA 和模式治理的大规模系统

代码对比

tRPC
// tRPC — 路由定义(服务端)
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
// db = Prisma/ORM 客户端(从单独的文件导入)

const t = initTRPC.create();

export const appRouter = t.router({
  getUser: t.procedure
    .input(z.object({ id: z.string() }))
    .query(async ({ input }) => {
      return db.user.findUnique({ where: { id: input.id } });
    }),
});

export type AppRouter = typeof appRouter;

// 客户端 — 服务端类型自动推导,无需 codegen
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './server';

const client = createTRPCClient<AppRouter>({
  links: [httpBatchLink({ url: 'http://localhost:3000/trpc' })],
});

const user = await client.getUser.query({ id: '1' });
// user: { id: string; name: string; ... } — 编译期完整类型安全
GraphQL
// graphql-js + @apollo/server — 在同一文件中定义 schema、resolver 和服务器
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';
// db = Prisma/ORM 客户端(从单独的文件导入)

const typeDefs = `#graphql
  type Post {
    id: ID!
    title: String!
  }

  type User {
    id: ID!
    name: String!
    posts: [Post!]!
  }

  type Query {
    user(id: ID!): User
  }
`;

const resolvers = {
  Query: {
    user: (_parent, { id }, { db }) => db.user.findUnique({ where: { id } }),
  },
  User: {
    posts: (user, _args, { db }) =>
      db.post.findMany({ where: { authorId: user.id } }),
  },
};

const server = new ApolloServer({ typeDefs, resolvers });

const { url } = await startStandaloneServer(server, {
  context: async () => ({ db }),
  listen: { port: 4000 },
});
console.log(`服务器已就绪: ${url}`);

// 客户端查询 — 只选择需要的字段:
// query { user(id: "1") { name posts { title } } }

结论

要看具体场景,'类型安全'本身不是选择 GraphQL 的理由。如果你只有一个 TypeScript monorepo 加一个 Web 客户端,tRPC 几乎总能带来更少的工作量——零代码生成,服务端一改动客户端立刻报 TS 错误。如果你有移动端应用、需要对外开放的公共 API,或者需要多团队联邦架构,GraphQL 的语言无关模式契约和 Apollo Federation 生态会带来结构性优势。

获取免费咨询
常见问题

常见问题

如果你在一个 TypeScript monorepo 中只服务一个 Web 客户端,tRPC 所需的代码和配置更少(零代码生成、端到端 TS 类型推导——trpc.io)。如果你有移动端应用、对外开放的公共 API,或者有多个独立服务,GraphQL 的模式契约与联邦生态(Apollo Federation)能提供更合适的抽象。

相关博客文章

查看全部文章
全部对比