tRPC库简介及其在演示名目中的运行解析

在近期关注的技术趋向中,一种名为tRPC的技术架构惹起了我的留意,它被宽泛运行于包括T3在内的多种现代技术堆栈中。但是,关于tRPC的实质及其广受欢迎的要素,我并不清楚。

我开局钻研和学习它。我不知道它的意思或目标是什么。所以,我深化钻研了RPC、gRPC和其余技术来寻觅答案。

我发现tRPC是一种用于设计API的类型安保架构格调。但该定义只是冰山一角,仅仅提醒了其深层外延的一小局部。

在本文中,我希冀能够更为深化地探求这座冰山的根源所在,清晰 tRPC 终究是何种事物。本文针对 tRPC 开展了深度阐释,涵盖了咱们为何须要它以及如何对其启动经常使用等方面。

请留意,作为这篇文章的撰写者,我是基于自身已有的钻研成绩,初次与你一同探求tRPC。此次探求重要面向初学者及新学者,如今就让咱们一同深化其中。

先决条件

你可以在此处找到本文的GitHub库和一切其余资源。

目录

什么是tRPC?

tRPC是一个基于TypeScript的类型安保库,它应用RPC API设计来解决API恳求并交付照应。

RPC代表远程环节调用。咱们的tRPC建设在RPC之上。RPC是一种设计API(如REST)的架构格调。经常使用RPC,你可以解脱Fetch和REST API。

望文生义,tRPC在RPC架构设计上减少了一个类型安保层。传统上,咱们经常使用REST API。它蕴含GET、POST、PULL等恳求类型。在tRPC中,没有恳求类型。

每个对tRPC后端的恳求都会经过查问系统,并依据输入和查问从tRPC后端取得照应。

相反,tRPC和react-query提供了内置函数来解决你的恳求。每个恳求都会失掉相反的解决。这取决于API端点能否接受输入、输入、修正等。

经常使用REST时,你会创立一个名为/api 的主文件夹,并在其中创立路由文件。但关于tRPC,你不须要蕴含许多文件的文件夹。你只要要几个内置函数和一个简化的react-query(反响查问)系统。

你无需经常使用fetch()、解决输入等。tRPC经常使用示意特定查问的URL启动操作,你将很快会看到。

为什么咱们须要tRPC?

tRPC确保RPC类型的安保。这示意客户端不可向主机发送与其预期不婚配的数据类型。例如,客户端不可为基于数字的属性传递字符串。

假设客户端尝试这样做,系统将立刻前往失误提醒-有效类型。若数据类型不婚配,集成开发环境(IDE)和阅读器将同步抛出失误。

类型安保是确保JavaScript运行程序稳固性和牢靠性的关键要素。tRPC框架正是应用TypeScript的强类型特性,极大地简化了后端路由的创立和操作口头环节。

tRPC的成功依赖于名为Zod的库。它为构建每个路由的数据形式提供了支持。所谓形式,是定义了属性且链接到每个属性的等效数据类型的对象。

例如,在须要用户详细消息的API路由中,开发人员将在后端定义一个对象,并应用Zod为该对象的每个属性指定相应的数据类型。

在前端,tRPC担任验证用户或API恳求所提供的数据能否与后端注册的数据类型相婚配,从而在前端和后端之间成功了类型安保的集成。

接上去,咱们将讨论tRPC、Zod以及其余关系库如何在演示名目中协同上班,以成功这一类型安保的集成。

如何经常使用tRPC

tRPC提供了一种高效的形式来极速搭建Express主机并开发tRPC路由和查问。其繁复的API设计使得开发环节变得直观且易于上手。

在传统的Wb运行架构中,客户端(前端)和主机端(后端)通常是分别的。本文示例将遵照这种架构形式,区分构建前后端系统。

让咱们首先经常使用React创立客户端,经常使用Express+CORS创立主机端来衔接它们。

文件夹结构

首先,创立一个名为tRPC Demo的主目录。在该主目录中,再创立另一个名为trpclibrary的子目录,用于分别客户端和主机端代码,并为后续作为一致库启动治理做预备。

在trpclibrary目录中,你将很快搁置主机端(Express)和客户端(React)的代码。

在tRPC Demo根目录中,拔出带有以下代码的package.json文件,作用是衔接一切的子文件夹,并准许经过繁多命令同时运转客户端和主机端。

{"name": "trpclibrary","version": "1.0.0","main": "index.js","license": "MIT","private": true,"scripts": {"start": "concurrently \"wsrun --parallel start\""},"workspaces": ["trpclibrary/*"],"devDependencies": {"concurrently": "^5.2.0","wsrun": "^5.2.0"}}

Root Directory package.json file

在根目录中性能完package.json文件后,下一步是在trpclibrary目录中搭建Express主机。

专业提醒:经常使用终端时,可以经过cd 命令进入文件夹并口头命令。假定你位于根目录中,则可以经常使用cd .\trpclibrary命令进入trpclibrary目录。VS Code的集成终端也雷同可以用于此操作。

为了极速初始化主机,咱们将经常使用 npx create-mf-app 启动命令。该命令会生成一个预约义的名目模板,清楚节俭初始设置期间。

Server-Side Setup

你或许会遇到失误提醒,指出你没有装置Express或其余库。不用担忧—你很快就会逐个装置一切必需的库。

成功搭建主机后,咱们将继续经常使用React和相反的命令在同一个trpclibrary目录下创立客户端。

Client-Side Setup

你的React客户端曾经预备就绪。但是,你或许会遇到与模块和包关系的各种失误。因此,让咱们首先下载它们。

我正在经常使用yarn,我倡导你也经常使用它。在trpcDemo根目录下口头yarn命令。

提醒:你可以经常使用cd ..命令来分开目录,并进入外部目录。

你的主机端或客户端,亦或是两者均或许缺少TypeScript性能文件。因此,我倡导在两个目录下区分口头npx tsc --init命令以启动装置。这样做将有助于初始化性能文件,确保名目能够顺利运转。

TS Configuration File Initialization

,你须要将tRPC、CORS和Zod下载到名目标主机端。

截至2024年7月2日,@trpc/server包的最新版本为10.45.2。请务必留意,即使是客户端的tRPC包也应坚持与主机端相反的版本,即10.45.2。

Installing Zod, CORS, and @trpc/server to the Server-Side

接上去,你须要为客户端装置@trpc/client,@trpc/react-query、@tanstack/react-query,@trpc/server和Zod。你可以经常使用相反的“yarn add”命令启动装置。

这次就不提供截图了,你可以参考前面的步骤尝试下载装置。

至此,咱们曾经成功了大局部装置和设置上班。以下是你的文件夹结构应当出现的外观:

tRPC Demo├── trpclibrary│ ├── client-side (React App Folder)│ ├── server-side (Express Server Folder)└── package.json

Folder Structure

tRPC设置

在本节中,咱们将口头以下义务:

首先,在主机端目录的index.ts文件中创立一个tRPC实例,依据文档说明,每个运行程序只应启动一个实例。

应用该tRPC实例创立一个路由器。该路由器协助你注册路由,以便API恳求抵达时能够启动解决。

路由是你解决恳求并前往照应的中央。它是衔接到Base URL的API端点。

例如,这个地址形容了名为hello的API端点,以及用于调用该API端点的Base URL api。

import { initTRPC } from "@trpc/server";import *as trpcExpress from "@trpc/server/adapters/express";const createContext = ({}: trpcExpress.CreateExpressContextOptions) =>({});type Context = Awaited>;const trpc = initTRPC.context().create();

你须要将以上代码段搁置在index.ts 文件中现有模板代码的上方,详细位置应在一切import语句之后,且位于申明app和port变量申明之前。同时,该代码段应位于express 模块的导入语句之下。

看!我经常使用了@trpc/server包中的initTRPC函数成功创立了一个tRPC实例。咱们将附丽此实例,来解决与后端关系的一切操作事务。

此外,我在tRPC路由器中减少了一个Context。这是tRPC的一项性能。它准许你将数据库衔接和身份验证消息等详细资料输入其中。

tRPC能够在一切tRPC环节之间共享Context。它作为一个消息存储和传递的场所,有助于防止代码冗余,并坚持代码的整洁有序。 到目前为止,你曾经经常使用了Context初始化了tRPC实例。接上去,你将对路由器启动编码—因此,请将以下代码减少到之前代码的下方:

import zod from "zod";const appRouter = trpc.router({hello: trpc.procedure.input(zod.object({name: zod.string(),})).query(({ input }) => {return {name: input.name,};}),});export type AppRouter = typeof appRouter;

最后,你引入了Zod库,同时,你还创立了一个名为hello的API端点,该端点经过经常使用input()方法接受输入,并将用户的API恳求与此端点定义的Zod对象启动婚配。

经过这段代码,Zod和tRPC都希冀前端传递的对象中蕴含一个基于字符串的名为name的属性。

你失掉输入,对其启动解构,并在query()方法中对其启动解决。这些操作都是tRPC流程的一局部。在tRPC的流程之间,Context会被共享。

正如我之前所述,你将在任何中央都须要tRPC实例。我用它来创立一个路由器来存储和注册路由(API端点),并对其启动解决。

在router()环节中,你可以创立有限数量的路由。它相似于一个路由解决程序,每个端点都是一个对象,每个路由都作为一个属性存在。

你将要求环节构建器提供对query()、input()等环节的访问权限。

如今,是时刻性能 Base URL了。在此阶段,你将经常使用@trpc/server库中的Express适配器来设置 Base URL。

将以下代码放在index.ts文件中,详细位置应在app.get()路由解决函数之前:

app.use("/api",trpcExpress.createExpressMiddleware({router: appRouter,createContext,}));

/api示意你的 Base URL。一切路由均位于/api URL之上。目前,你的hello API端点已性能为。

接上去,让咱们尝试经常使用阅读器启动测试。你能否还记得我曾要求你在tRPC Demo根目录下创立一个蕴含预设代码的package.json文件吗?

该文件旨在成功主机端和客户端的库式一体化运转。请将终端切换至根目录,并口头yarn start命令以启动主机和客户端。启动成功后,请访问网址。

tRPC Invalid Type Error

你能否遇到了失误提醒?假设提醒显示为“有效类型”,那么你走在正确的路线上。看,这就是tRPC为咱们提供的协助所在。

在上方的代码中,当我以用户身份向hello API端点发送API恳求时,我没有传递tRPC希冀该端点的任何对象或值。

tRPC希冀的是一个蕴含一个基于字符串的属性名为name的对象,并且须要为其提供一个值。当我没有提供它时,tRPC就会限度我的访问权限。这正是tRPC的杰出之处。

“这一切都很好,但是如今怎样办?”你必定将前端与主机端衔接起来,以便发送蕴含预期数据的对象。

至于主机端,还有一件事件须要留意,那就是CORS(跨源资源共享)!设置CORS十分便捷。请在index.ts文件中找到Express框架的初始化代码,这个代码是Express模板自带的。而后,在该代码中拔出以下代码行:

import cors from "cors";app.use(cors());

在你的index.ts文件中,请细心查找无关端口设置与运行性能变量的申明局部。

一旦减少关系代码行,或许会产生失误提醒,那是由于你尚未装置CORS的类型定义。请前往终端并在主机端目录下装置@types/cors。

@types/cors download.

CORS已预备就绪且安保。主机端已搭建终了!如今,让咱们尝试经常使用各自的库来成功主机端和客户端的衔接。

在咱们转向客户端之前,我需确定咱们在同一个页面上。到目前为止,你曾经创立了一个tRPC实例,构成了一个路由器,设定了基本URL,并经过可选的Context对API端点启动测试。

以上一切性能和代码均已在主机端的index.ts文件中成功。让咱们转到客户端并攻克本教程的最后一局部。

客户端

咱们曾经下载了所需的包。接上去,咱们将在客户端目录下的/src子目录中创立一个trpc.ts文件。该文件将担任解决前端收回的查问和恳求。

在主机端,你曾经创立了一个 tRPC 实例来构建路由器和其余组件。如今,你须要在客户端启动相反的操作。为此,你须要经常使用@trpc/react-query来创立一个客户端 tRPC 实例。

此外,为了将客户端 tRPC 实例与主机端实例相衔接,你必定导入主机端的 tRPC 实例及其类型定义。

要导入主机端 tRPC 实例,请在主机端的package.json文件中减少一个main 属性。这样,当你在客户端导入主机端文件夹时,它将智能将index.ts文件设置为入口点。

Server-Side package.json file.

设置该属性后,你便可以经过终端将tRPC实例导入客户端。对我来说,在我的package.json文件中,位于主机端目录下的后端模块称为server-side,版本为1.0.0。

因此,我将在客户端终端中口头yarn add server-side@1.0.0命令。这一装置环节或许看起来颇为相熟,由于它正是开发者构建库的惯例形式。

此命令应将你的主机端文件夹作为包减少至客户端节点模块目录中。你可以经过检查客户端的package.json文件来验证这一点。

Client-Side package.json file.

它应当将你的主机端包名列为依赖项。

换句话说,你曾经在客户端运行程序中装置了主机端包。如今,你可以导入主机端tRPC,并将其作为库来经常使用。

回顾之前,咱们在主机端创立路由器时,特地减少了额外的导出AppRout类型语句。咱们之所以这么做,是由于必定在客户端导入AppRouter类型,这样能力在客户端经常使用主机端的tRPC实例。

以下是trpc.ts文件目前的代码结构:

import { createTRPCReact } from"@trpc/react-query";import type { AppRouter } from "server-side";export const trpc = createTRPCReact();

trpc.ts file.

经常使用此代码,你曾经应用了主机端tRPC实例的特色成功的构建了客户端tRPC实例。

接上去,咱们将在/src目录下创立一个名为AppComponent.tsx的新文件。

该文件将担任寄存主运行组件,它将从trpc.ts文件中导入tRPC客户端实例,并应用该实例调用hello API端点。

import React from "react";import { trpc } from "./trpc";

AppComponent.tsx import statements.

鉴于你曾经成功创立了tRPC客户端实例,你如今可以访问该客户端的所有API端口,并应用useQuery( )方法向这些API端口动员恳求。

import React from "react";import { trpc } from"./trpc";const AppComponent = () => {const userQuery = trpc.hello.useQuery({ name: "Afan" });return ({JSON.stringify(userQuery.data?.name)});};export default AppComponent;

Entire AppComponent.tsx file.

假设你还记得,hello API端点须要一个带有字符串类型值的name属性的对象。因此,你将经常使用带有值的useQuery( )方法传递对象,以防止tRPC的参数不婚配疑问。

在JSX代码中,你将应用JSON.stringify( )方法解构API端点前往的API照应,并由API端点访问结果。

你的AppComponent.tsx文件是一个规范的React组件,因此须要将其导入到主App.tsx文件中。在客户端,App.tsx文件相当于主机端的index.ts。

关于App.tsx文件,你将遵照相似的性能流程。首先,从trpc.ts文件中导入客户端tRPC实例。而后,设置 Base URL并性能React Query。

你将从TanStack导入React Query,从./trpc.ts文件中导入trpc,从@trpc/client导入httpBatchLink,从React导入useState,从AppComponent.tsx文件中导入AppComponent。

// Default Import Statementsimport React from "react";import ReactDOM from "react-dom/client";import "./index.scss";// Add the following Import Statementsimport { useState } from "react";import { trpc } from "./trpc";import { httpBatchLink } from "@trpc/client";import AppComponent from "./AppComponent";import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

你将逐个经常使用每个导入语句,无需担忧关于未经常使用导入对象的失误。接着,仿照tRPC的做法,创立一个React Query客户端实例。

const client = new QueryClient();

成功此操作后,你须要设置Base URL。这一步骤将在主运行程序的性能局部启动。

此外,请将位于App函数下的代码语句移至React Query客户端申明语句之后,搁置在App函数的顶部位置。

const rootElement = document.getElementById("app");if (!rootElement) throw new Error("Failed to find the root element");const root = ReactDOM.createRoot(rootElement as HTMLElement);

而后,你须要从App函数中移除自动的JSX超文本标志言语代码。你可以安心肠安保删除App函数中的一切超文本标志言语内容。

接上去,你须要为客户端设置Base URL。每端启动API端点调用时,都会经常使用这个Base URL。它应该与你在主机端设置的Base URL坚持分歧。

请将App性能代码从HTML中交流为以下Base URL代码:

const App = () => {const [trpcClient] = useState(() =>trpc.createClient({links: [httpBatchLink({// Base URLurl: "http://localhost:3005/api",}),],}));return <>;};

你的App.tsx文件,如下所示:

import React from "react";import ReactDOM from "react-dom/client";import "./index.scss";import { useState } from "react";import { trpc } from "./trpc";import { httpBatchLink } from "@trpc/client";import AppComponent from "./AppComponent";import { QueryClient, QueryClientProvider } from "@tanstack/react-query";const client = new QueryClient();const rootElement = document.getElementById("app");if (!rootElement) throw new Error("Failed to find the root element");const root = ReactDOM.createRoot(rootElement as HTMLElement);const App = () => {const [trpcClient] = useState(() =>trpc.createClient({links: [httpBatchLink({// Base URLurl: "http://localhost:3005/api",}),],}));return <>;};root.render();

我尚未详细讨论return语句的详细用法。所以,就让咱们如今来启动这项讨论。咱们不准许return语句为空。

该语句将显示API端点前往的数据,这些数据应是经过在AppComponent.tsx组件文件中调用useQuery( )方法提交的字符串。

return语句重要供包装器及AppComponent 组件经常使用。若组件和页面须要驳回 tRPC、React Query 等技术,则必定经常使用这些库的 Providers 来打包 AppComponent 组件。

return (// tRPC Provider{/* React Query Provider */}{/* HTML React Component */});

如今,你将经常使用React Query打包AppComponent组件,并在该文件中传递你经过调用QueryClient( )创立的React Query客户端实例。而后,你将应用tRPC Provider打包React Query Provider。

The tRPC Provider 须要React Query客户端和带有Base URL的tRPC客户端。因此,咱们也将提供该消息。

一旦你传递了所需消息并确保代码与咱们的代码相婚配,你就可以访问并检查输入。该页面将显示你经过hello API端点传递的数据。

留意:你应该在tRPC Demo目录下运转yarn start命令,关上localhost端口以检查输入结果。

输入图像

咱们曾经预备就绪。tRPC准许咱们从前端调用hello API端点。它优先思索类型安保,并驳回TypeScript来防止数以百万计的其余JavaScript或许带来的疑问。

你可以在Route解决程序中减少更多路由和API端点,比如hello。这就像给对象减少新属性一样便捷。tRPC就是这样让你的开发上班变得愈加轻松。

论断

tRPC是一个类型安保的RPC样式库。它将RPC与TypeScript深度集成,旨在消弭REST、fetch( )和其余创立和调用API的技术所带来的疑问。

它作为REST和Fetch的代替打算。我将在可预感的未来继续经常使用它。

译者引见

刘涛,社区编辑,某大型央企系统上线检测管控担任人。

文章题目:What is the tRPC Library? Explained with a Demo Project (freecodecamp.org),作者:Afan Khan

您可能还会对下面的文章感兴趣: