tRPC 简介 #

什么是 RPC? #

在了解 tRPC 之前,我们需要先理解 RPC(Remote Procedure Call,远程过程调用)的概念。RPC 是一种协议,允许程序调用另一个地址空间(通常在网络上的另一台机器)的过程或函数,就像调用本地函数一样。

text
┌─────────────────────────────────────────────────────────────┐
│                    RPC 的本质                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   传统方式:                                                 │
│                                                             │
│   ┌─────────┐    HTTP 请求     ┌─────────┐                 │
│   │  客户端  │ ───────────────> │  服务端  │                 │
│   └─────────┘                  └─────────┘                 │
│                                                             │
│   需要手动:                                                 │
│   - 定义 API 路由                                           │
│   - 序列化/反序列化数据                                      │
│   - 处理类型转换                                            │
│   - 维护前后端类型一致性                                     │
│                                                             │
│   RPC 方式:                                                 │
│                                                             │
│   ┌─────────┐    直接调用      ┌─────────┐                 │
│   │  客户端  │ ───────────────> │  服务端  │                 │
│   └─────────┘    server.add()   └─────────┘                 │
│                                                             │
│   就像调用本地函数一样!                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

传统 API 开发的痛点 #

text
┌─────────────────────────────────────────────────────────────┐
│                    传统开发流程                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 后端定义接口                                            │
│     ┌─────────────────────────────────────────┐            │
│     │ // 定义 REST API                        │            │
│     │ POST /api/users                        │            │
│     │ GET  /api/users/:id                    │            │
│     │ PUT  /api/users/:id                    │            │
│     └─────────────────────────────────────────┘            │
│                                                             │
│  2. 编写 API 文档 / Swagger                                 │
│     ┌─────────────────────────────────────────┐            │
│     │ openapi: 3.0.0                         │            │
│     │ paths:                                 │            │
│     │   /api/users:                          │            │
│     │     post:                              │            │
│     │       requestBody: ...                 │            │
│     └─────────────────────────────────────────┘            │
│                                                             │
│  3. 前端定义类型                                            │
│     ┌─────────────────────────────────────────┐            │
│     │ interface User {                       │            │
│     │   id: number;                          │            │
│     │   name: string;                        │            │
│     │ }                                      │            │
│     └─────────────────────────────────────────┘            │
│                                                             │
│  4. 前端调用 API                                            │
│     ┌─────────────────────────────────────────┐            │
│     │ const res = await fetch('/api/users'); │            │
│     │ const user = await res.json();         │            │
│     └─────────────────────────────────────────┘            │
│                                                             │
│  问题:                                                     │
│  ❌ 类型定义重复                                           │
│  ❌ 前后端类型可能不一致                                    │
│  ❌ API 变更需要同步更新                                    │
│  ❌ 没有编译时类型检查                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

什么是 tRPC? #

tRPC(TypeScript Remote Procedure Call)是一个用于 TypeScript 的端到端类型安全 RPC 框架。它允许你在不定义任何 schema 的情况下,直接从 TypeScript 前端调用后端函数,并享受完整的类型安全和自动补全。

核心定位 #

text
┌─────────────────────────────────────────────────────────────┐
│                         tRPC                                 │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  端到端类型   │  │  零 Schema   │  │  自动补全    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  轻量级      │  │  框架无关    │  │  开发体验    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
└─────────────────────────────────────────────────────────────┘

tRPC 解决的问题 #

text
┌─────────────────────────────────────────────────────────────┐
│                    tRPC 解决的问题                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  传统 TypeScript 全栈开发痛点:                              │
│                                                             │
│  1. 类型同步问题                                            │
│     前后端各自定义类型                                       │
│     API 变更时需要手动同步                                   │
│     容易出现类型不一致                                       │
│                                                             │
│  2. Schema 维护成本                                         │
│     需要维护 OpenAPI/GraphQL Schema                         │
│     代码生成步骤繁琐                                         │
│     增加项目复杂度                                           │
│                                                             │
│  3. 开发效率低下                                            │
│     没有自动补全                                            │
│     需要查阅 API 文档                                       │
│     运行时才能发现错误                                       │
│                                                             │
│  tRPC 解决方案:                                             │
│                                                             │
│  ✅ 端到端类型安全:前后端共享类型                           │
│  ✅ 零 Schema:直接使用 TypeScript 类型                      │
│  ✅ 自动补全:IDE 智能提示                                  │
│  ✅ 编译时检查:提前发现错误                                 │
│  ✅ 极简开发:像调用本地函数一样                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

tRPC 的历史 #

发展历程 #

text
2020年 ─── tRPC 项目启动
    │
    │      Alex Johansson 创建
    │      为 TypeScript 全栈开发设计
    │
2021年 ─── 开源发布
    │
    │      GitHub 开源
    │      社区快速增长
    │
2022年 ─── 生态扩展
    │
    │      支持 Next.js、React、Vue
    │      插件系统完善
    │
2023年 ─── 企业采用
    │
    │      大量公司采用
    │      生态成熟
    │
至今   ─── 行业标准
    │
    │      GitHub 30k+ Stars
    │      TypeScript 全栈首选方案

里程碑版本 #

版本 时间 重要特性
1.0 2021 初始发布,核心 RPC 功能
9.0 2022 稳定版本,完整生态支持
10.0 2023 全新 API 设计,性能优化
11.0 2024 更好的类型推断,新特性

tRPC 的核心特点 #

1. 端到端类型安全 #

text
┌─────────────────────────────────────────────────────────────┐
│                    端到端类型安全                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  后端定义:                                                  │
│  ┌─────────────────────────────────────────┐               │
│  │ const router = t.router({               │               │
│  │   user: {                               │               │
│  │     getById: t.procedure                │               │
│  │       .input(z.object({ id: z.number()}))│              │
│  │       .output(z.object({                │               │
│  │         id: z.number(),                 │               │
│  │         name: z.string()                │               │
│  │       }))                               │               │
│  │       .query(({ input }) => {           │               │
│  │         return { id: input.id, name: 'John' }│          │
│  │       })                                │               │
│  │   }                                     │               │
│  │ })                                      │               │
│  └─────────────────────────────────────────┘               │
│                                                             │
│  前端调用:                                                  │
│  ┌─────────────────────────────────────────┐               │
│  │ const user = await trpc.user.getById    │               │
│  │   .query({ id: 1 });                    │               │
│  │                                         │               │
│  │ // user 类型自动推断为:                 │               │
│  │ // { id: number; name: string }         │               │
│  │                                         │               │
│  │ // ✅ 完整的自动补全                    │               │
│  │ // ✅ 编译时类型检查                    │               │
│  │ // ✅ 重构时自动更新                    │               │
│  └─────────────────────────────────────────┘               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2. 零 Schema 定义 #

text
┌─────────────────────────────────────────────────────────────┐
│                    零 Schema 设计                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  传统方式(需要 Schema):                                   │
│                                                             │
│  GraphQL:                                                   │
│  type User {                                                │
│    id: ID!                                                  │
│    name: String!                                            │
│  }                                                          │
│  type Query {                                               │
│    user(id: ID!): User                                      │
│  }                                                          │
│                                                             │
│  OpenAPI:                                                   │
│  paths:                                                     │
│    /users/{id}:                                             │
│      get:                                                   │
│        parameters: ...                                      │
│        responses: ...                                       │
│                                                             │
│  tRPC 方式(零 Schema):                                    │
│                                                             │
│  const router = t.router({                                  │
│    user: {                                                  │
│      getById: t.procedure                                   │
│        .input(z.object({ id: z.number() }))                 │
│        .query(({ input }) => {                              │
│          return db.user.findUnique({ where: { id: input.id }})│
│        })                                                   │
│    }                                                        │
│  })                                                         │
│                                                             │
│  ✅ 直接使用 TypeScript/Zod 类型                            │
│  ✅ 无需额外定义 Schema                                     │
│  ✅ 类型自动推断和共享                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3. 框架无关 #

text
┌─────────────────────────────────────────────────────────────┐
│                    框架无关设计                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  服务端支持:                                                │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐              │
│  │  Next.js  │  │  Express  │  │  Fastify  │              │
│  └───────────┘  └───────────┘  └───────────┘              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐              │
│  │  NestJS   │  │  Hono     │  │  Node.js  │              │
│  └───────────┘  └───────────┘  └───────────┘              │
│                                                             │
│  客户端支持:                                                │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐              │
│  │  React    │  │  Vue      │  │  Svelte   │              │
│  └───────────┘  └───────────┘  └───────────┘              │
│  ┌───────────┐  ┌───────────┐  ┌───────────┐              │
│  │  Solid    │  │  Next.js  │  │  Nuxt     │              │
│  └───────────┘  └───────────┘  └───────────┘              │
│                                                             │
│  移动端支持:                                                │
│  ┌───────────┐  ┌───────────┐                              │
│  │  React    │  │  React    │                              │
│  │  Native   │  │  Native   │                              │
│  └───────────┘  └───────────┘                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4. 轻量级 #

text
┌─────────────────────────────────────────────────────────────┐
│                    轻量级设计                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  包大小对比:                                                │
│                                                             │
│  tRPC 核心:     ~10KB (gzip)                               │
│  GraphQL:       ~50KB+ (需要 Apollo 等客户端)               │
│  REST + Axios:  ~15KB                                      │
│                                                             │
│  依赖关系:                                                  │
│                                                             │
│  tRPC:                                                       │
│  - @trpc/server                                            │
│  - @trpc/client                                            │
│  - 无其他必需依赖                                           │
│                                                             │
│  优势:                                                     │
│  ✅ 最小化依赖                                              │
│  ✅ 快速安装                                                │
│  ✅ 小包体积                                                │
│  ✅ 无运行时开销                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

tRPC vs 其他方案 #

tRPC vs REST #

特性 tRPC REST
类型安全 ✅ 端到端 ❌ 需要额外工具
Schema ✅ 零 Schema ⚠️ 需要 OpenAPI
自动补全 ✅ 完整 ❌ 无
学习曲线 ✅ 低 ✅ 低
通用性 ⚠️ TypeScript 限定 ✅ 语言无关
缓存 ⚠️ 需要处理 ✅ HTTP 缓存

tRPC vs GraphQL #

特性 tRPC GraphQL
类型安全 ✅ 原生 TypeScript ✅ Schema 定义
Schema ✅ 零 Schema ⚠️ 需要定义
学习曲线 ✅ 低 ⚠️ 中等
包大小 ✅ 小 ⚠️ 较大
灵活性 ⚠️ 固定查询 ✅ 灵活查询
生态 🔄 发展中 ✅ 成熟

tRPC vs gRPC #

特性 tRPC gRPC
语言支持 ⚠️ TypeScript ✅ 多语言
类型安全 ✅ TypeScript ✅ Protobuf
学习曲线 ✅ 低 ⚠️ 高
性能 ✅ 好 ✅ 极好
浏览器支持 ✅ 原生 ⚠️ 需要 gRPC-Web
开发体验 ✅ 极佳 ⚠️ 一般

tRPC 的应用场景 #

1. Next.js 全栈应用 #

text
┌─────────────────────────────────────────────────────────────┐
│                    Next.js + tRPC                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  项目结构:                                                  │
│                                                             │
│  src/                                                       │
│  ├── pages/                                                 │
│  │   ├── api/                                              │
│  │   │   └── trpc/[trpc].ts    # tRPC API 路由             │
│  │   ├── _app.tsx             # 配置 tRPC Provider         │
│  │   └── index.tsx            # 页面组件                   │
│  │                                                          │
│  ├── server/                                                │
│  │   ├── routers/            # tRPC 路由定义               │
│  │   │   ├── user.ts                                       │
│  │   │   └── post.ts                                       │
│  │   └── trpc.ts             # tRPC 配置                   │
│  │                                                          │
│  └── utils/                                                 │
│      └── trpc.ts             # 客户端 tRPC 配置            │
│                                                             │
│  优势:                                                     │
│  ✅ 无需额外 API 服务器                                     │
│  ✅ SSR/SSG 支持                                           │
│  ✅ 开发体验极佳                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2. 独立前后端项目 #

text
┌─────────────────────────────────────────────────────────────┐
│                    独立前后端架构                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────┐         ┌─────────────────┐          │
│   │   前端项目       │         │   后端项目       │          │
│   │   (React/Vue)   │         │   (Node.js)     │          │
│   │                 │  HTTP   │                 │          │
│   │  @trpc/client   │ <─────> │  @trpc/server   │          │
│   │                 │         │                 │          │
│   │  共享类型包     │ <─────> │  共享类型包     │          │
│   └─────────────────┘         └─────────────────┘          │
│                                                             │
│  共享类型包:                                                │
│  packages/                                                  │
│  └── shared/                                                │
│      ├── package.json                                       │
│      └── src/                                               │
│          └── types.ts       # 共享类型定义                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3. 微服务通信 #

text
┌─────────────────────────────────────────────────────────────┐
│                    微服务架构                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────┐     ┌─────────┐     ┌─────────┐              │
│  │ API     │     │ User    │     │ Order   │              │
│  │ Gateway │────>│ Service │     │ Service │              │
│  └─────────┘     └─────────┘     └─────────┘              │
│       │               │               │                    │
│       │               │               │                    │
│       ▼               ▼               ▼                    │
│  ┌─────────────────────────────────────────────┐          │
│  │              tRPC 内部通信                    │          │
│  │         TypeScript 类型安全调用              │          │
│  └─────────────────────────────────────────────┘          │
│                                                             │
│  优势:                                                     │
│  ✅ 服务间类型安全                                          │
│  ✅ 统一的调用方式                                          │
│  ✅ 简化服务发现                                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4. 移动端应用 #

text
┌─────────────────────────────────────────────────────────────┐
│                    移动端应用                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  React Native 项目:                                        │
│                                                             │
│  App.tsx                                                    │
│  ├── 使用 @trpc/client                                     │
│  ├── 完整类型安全                                          │
│  └── 与 Web 共享类型                                       │
│                                                             │
│  示例:                                                     │
│  const { data } = trpc.user.getById.useQuery({ id: 1 });   │
│                                                             │
│  优势:                                                     │
│  ✅ 与 Web 共享后端                                         │
│  ✅ 类型安全 API 调用                                       │
│  ✅ 一致的开发体验                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

tRPC 的核心概念 #

Router(路由器) #

typescript
import { t } from './trpc';

const userRouter = t.router({
  getById: t.procedure.query(() => { /* ... */ }),
  create: t.procedure.mutation(() => { /* ... */ }),
});

const appRouter = t.router({
  user: userRouter,
  post: postRouter,
});

Procedure(过程) #

typescript
const router = t.router({
  query: t.procedure
    .input(z.object({ id: z.number() }))
    .query(({ input }) => {
      return { id: input.id, name: 'John' };
    }),
    
  mutation: t.procedure
    .input(z.object({ name: z.string() }))
    .mutation(({ input }) => {
      return { success: true };
    }),
    
  subscription: t.procedure
    .subscription(() => {
      return observable((observer) => {
        observer.next({ data: 'update' });
      });
    }),
});

Context(上下文) #

typescript
interface Context {
  user?: User;
  req: Request;
}

const t = initTRPC.context<Context>().create();

const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
  if (!ctx.user) {
    throw new TRPCError({ code: 'UNAUTHORIZED' });
  }
  return next();
});

tRPC 的优势 #

text
✅ 极致开发体验
   - 自动补全
   - 类型推断
   - 即时反馈

✅ 类型安全
   - 端到端类型
   - 编译时检查
   - 重构友好

✅ 零配置
   - 无需 Schema
   - 无需代码生成
   - 开箱即用

✅ 灵活架构
   - 框架无关
   - 多种部署方式
   - 可扩展设计

✅ 高性能
   - 轻量级
   - 无运行时开销
   - 按需加载

tRPC 的局限性 #

text
⚠️ TypeScript 限定
   - 必须使用 TypeScript
   - 前后端都需要 TypeScript
   - 不适合多语言项目

⚠️ 紧耦合
   - 前后端需要共享类型
   - 需要共享代码包
   - 版本同步要求

⚠️ 公开 API
   - 不适合公开 API
   - 需要额外处理文档
   - 第三方集成困难

⚠️ 学习曲线
   - 需要理解 tRPC 概念
   - 需要熟悉 Zod 等库
   - 调试方式不同

学习路径 #

text
入门阶段
├── tRPC 简介(本文)
├── 快速开始
└── 路由器与过程

进阶阶段
├── 客户端使用
├── 类型系统
├── 中间件
└── 错误处理

高级阶段
├── 高级特性
├── 性能优化
├── 测试策略
└── 生产部署

实战阶段
├── Next.js 集成
├── React 项目实战
├── Vue 项目实战
└── 最佳实践

适用场景判断 #

text
┌─────────────────────────────────────────────────────────────┐
│                    选择指南                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  推荐使用 tRPC:                                             │
│  ✅ TypeScript 全栈项目                                    │
│  ✅ Next.js 应用                                           │
│  ✅ 内部 API / 私有项目                                    │
│  ✅ 快速原型开发                                            │
│  ✅ 小型到中型团队                                          │
│                                                             │
│  不推荐使用 tRPC:                                           │
│  ❌ 需要公开 API                                           │
│  ❌ 多语言项目                                              │
│  ❌ 非 TypeScript 项目                                     │
│  ❌ 需要复杂查询(考虑 GraphQL)                            │
│  ❌ 需要严格版本控制                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

下一步 #

现在你已经了解了 tRPC 的基本概念,接下来学习 快速开始,开始构建你的第一个 tRPC 应用!

最后更新:2026-03-29