因为不用monorepo而放弃tRPC?教你如何在前后端分开项目中使用tRPC

之前写过一篇关于tRPC的文章 还在前后端分离?来试试tRPC与Next.js吧! - 掘金 (juejin.cn),评论里有同学问在前后端分离的项目中可以使用吗,钻研了一下在前后端分开的项目中的如何使用trpc。

最简单的方式应该直接把server上传为包(没试过),然后让客户端安装就行,但是这样可能会让一些自动生成的类型的库无效比如prisma。所以还得优化一下

创建示例项目

首先先创建两个仓库的文件,client和server,执行pnpm init初始化项目,都创建一个index.ts文件

server

  1. server 安装依赖 pnpm i typescript @trpc/server zod
  2. 创建tsconfig.json文件,我们制定编译后js代码的输出路径为./dist,类型声明的输出路径为./types,strict必须设置为true。
json 复制代码
{
  "compilerOptions": {
    "composite": true,
    "strict": true,
    "outDir": "./dist",
    "declarationDir": "./types",
    "removeComments": false
  },
  "include": ["./"]
}
  1. 复制官方实例,简单写一个trpc程序
ts 复制代码
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
import { createHTTPServer } from '@trpc/server/adapters/standalone';

const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;

const appRouter = router({
  /** 这是测试!! */
  test: publicProcedure
    .input(
      z.object({
        field1: z.number(),
        field2: z.string(),
      }),
    )
    .query(async () => {
      return {
        date: new Date(),
        number: 1,
        string: 1,
        nested: {
          a: 1,
        },
        array: [],
      };
    }),
});

export type AppRouter = typeof appRouter;

const server = createHTTPServer({
  router: appRouter,
});

server.listen(3000);
  1. 然后直接运行tsc,编译整个项目。得到编译后文件types/index.d.ts文件,

client

  1. 先安装依赖pnpm install typescript @trpc/client
  2. 把server发包有点麻烦了,这里为了方便我们直接使用pnpm link ../server直接模拟安装了server的依赖(lotus-trpc-server),npm也可以直接把gihub的仓库当成依赖,不需要发包。
  1. 照着官方示例写点代码,并且AppRouter的类型从server获取
ts 复制代码
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from 'lotus-trpc-server/types'; // 从后端拿到的AppRouter
type ErrorShape = AppRouter['_def']['_config']['$types']['errorShape'];

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

trpc.test
  .query({})
  .then((res) => {})
  .catch((err: ErrorShape) => {});
  1. 让我们来检验一下成果

可以看到catch这里我搞了个骚操作,把后端的error类型拿到了。

后端的注释文档也是正常显示的

ok,一切运行正常,非常完美!在我的另一个使用prisma的项目中也进行了测试,可以正常拿到prisma的类型。

其他

可能会有人觉得ts的类型有时候不够直观,完全看不出要传什么 可以参考一下这个类型工具,可以把ide提示的字段扩展开,更直观看到有什么字段visual studio code - How can I see the full expanded contract of a Typescript type? - Stack Overflow

ts 复制代码
export type Expand<T> = T extends (...args: infer A) => infer R
  ? (...args: Expand<A>) => Expand<R>
  : T extends infer O
  ? { [K in keyof O]: O[K] }
  : never;

export type ExpandRecursively<T> = T extends (...args: infer A) => infer R
  ? (...args: ExpandRecursively<A>) => ExpandRecursively<R>
  : T extends object
  ? T extends infer O
    ? { [K in keyof O]: ExpandRecursively<O[K]> }
    : never
  : T;

使用前:

使用后:

这下没有理由不使用tRPC了吧,都给我狠狠的用!

相关推荐
飘尘1 天前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
onething3653 天前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 5 —— SSE 流式输出 + 打字机效果
人工智能·后端·全栈
onething3653 天前
Spring Boot + Spring AI 从入门到实战:7天转型计划 Day 6 —— 业务完善 + 会话消息预览
人工智能·后端·全栈
东坡白菜3 天前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
程序员黑豆5 天前
AI全栈开发系列开篇:从Java全栈到AI应用实战
前端·ai编程·全栈
chengliu05086 天前
从前端转型全栈、 Agent 开发
程序员·全栈
智码看视界8 天前
老梁聊全栈系列 JavaScript语言本质:从原型链到异步编程的深度解析
开发语言·javascript·全栈·javascript核心
To_OC8 天前
我一直以为 Ajax 是个黑盒,直到我写了这 50 行代码
前端·后端·全栈
JustHappy12 天前
古法编程秘籍(六):程序到底是怎么跑起来的?从 IO 到中断,一次讲明白
前端·后端·全栈
该用户已不存在12 天前
这9款开发工具夯爆了,用了都说好
后端·程序员·全栈