自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

tRPC庫簡介及其在演示項目中的應用解析

譯文 精選
開發(fā) 后端
在本文中,我期望能夠更為深入地探究這座冰山的根源所在,明晰 tRPC 究竟是何種事物。本文針對 tRPC 展開了深度闡釋,涵蓋了我們?yōu)楹涡枰约叭绾螌ζ溥M行使用等方面。

譯者 | 劉濤

審校 | 重樓

在近期關注的技術趨勢中,一種名為tRPC的技術架構引起了我的注意,它被廣泛應用于包括T3在內(nèi)的多種現(xiàn)代技術堆棧中。然而,對于tRPC的本質及其廣受歡迎的原因,我并不清楚。

我開始研究和學習它。我不知道它的意思或目的是什么。所以,我深入研究了RPC、gRPC和其他技術來尋找答案。

我發(fā)現(xiàn)tRPC是一種用于設計API的類型安全架構風格。但該定義只是冰山一角,僅僅揭示了其深層內(nèi)涵的一小部分。

在本文中,我期望能夠更為深入地探究這座冰山的根源所在,明晰 tRPC 究竟是何種事物。本文針對 tRPC 展開了深度闡釋,涵蓋了我們?yōu)楹涡枰约叭绾螌ζ溥M行使用等方面。

請注意,作為這篇文章的撰寫者,我是基于自身已有的研究成果,首次與你一同探究tRPC。此次探索主要面向初學者及新學者,現(xiàn)在就讓我們一同深入其中。

先決條件

  • 中級JavaScript知識
  • 基本的TypeScript知識
  • 中級React知識
  • Fetch和REST API的使用經(jīng)驗
  • 使用終端或控制臺的經(jīng)驗
  • 使用NPM及其命令的經(jīng)驗
  • 使用CORS以及連接前端/后端的經(jīng)驗
  • 熱衷于學習新知識

你可以在此處找到本文的GitHub庫和所有其他資源。

目錄

  • 什么是tRPC?
  • 為什么我們需要tRPC?
  • 如何使用tRPC
  • 結論

什么是tRPC?

tRPC是一個基于TypeScript的類型安全庫,它利用RPC API設計來處理API請求并交付響應。

RPC代表遠程過程調用。我們的tRPC建立在RPC之上。RPC是一種設計API(如REST)的架構風格。使用RPC,你可以擺脫Fetch和REST API。

顧名思義,tRPC在RPC架構設計上添加了一個類型安全層。傳統(tǒng)上,我們使用REST API。它包含GET、POST、PULL等請求類型。在tRPC中,沒有請求類型。

每個對tRPC后端的請求都會通過查詢系統(tǒng),并根據(jù)輸入和查詢從tRPC后端獲得響應。

相反,tRPC和react-query提供了內(nèi)置函數(shù)來處理你的請求。每個請求都會得到相同的處理。這取決于API端點是否接受輸入、輸出、修改等。

使用REST時,你會創(chuàng)建一個名為/api 的主文件夾,并在其中創(chuàng)建路由文件。但對于tRPC,你不需要包含許多文件的文件夾。你只需要幾個內(nèi)置函數(shù)和一個簡化的react-query(反應查詢)系統(tǒng)。

你無需使用fetch()、處理輸出等。tRPC使用表示特定查詢的URL進行操作,你將很快會看到。

為什么我們需要tRPC?

tRPC確保RPC類型的安全。這表示客戶端無法向服務器發(fā)送與其預期不匹配的數(shù)據(jù)類型。例如,客戶端無法為基于數(shù)字的屬性傳遞字符串。

如果客戶端嘗試這樣做,系統(tǒng)將立即返回錯誤提示-無效類型。若數(shù)據(jù)類型不匹配,集成開發(fā)環(huán)境(IDE)和瀏覽器將同步拋出錯誤。

類型安全是確保JavaScript應用程序穩(wěn)定性和可靠性的關鍵要素。tRPC框架正是利用TypeScript的強類型特性,極大地簡化了后端路由的創(chuàng)建和操作執(zhí)行過程。

tRPC的實現(xiàn)依賴于名為Zod的庫。它為構建每個路由的數(shù)據(jù)模式提供了支持。所謂模式,是定義了屬性且鏈接到每個屬性的等效數(shù)據(jù)類型的對象。

例如,在需要用戶詳細信息的API路由中,開發(fā)人員將在后端定義一個對象,并利用Zod為該對象的每個屬性指定相應的數(shù)據(jù)類型。

在前端,tRPC負責驗證用戶或API請求所提供的數(shù)據(jù)是否與后端注冊的數(shù)據(jù)類型相匹配,從而在前端和后端之間實現(xiàn)了類型安全的集成。

接下來,我們將探討tRPC、Zod以及其他相關庫如何在演示項目中協(xié)同工作,以實現(xiàn)這一類型安全的集成。

如何使用tRPC

tRPC提供了一種高效的方式來快速搭建Express服務器并開發(fā)tRPC路由和查詢。其簡潔的API設計使得開發(fā)過程變得直觀且易于上手。

在傳統(tǒng)的Wb應用架構中,客戶端(前端)和服務器端(后端)通常是分離的。本文示例將遵循這種架構模式,分別構建前后端系統(tǒng)。

讓我們首先使用React創(chuàng)建客戶端,使用Express+CORS創(chuàng)建服務器端來連接它們。

文件夾結構

首先,創(chuàng)建一個名為tRPC Demo的主目錄。在該主目錄中,再創(chuàng)建另一個名為trpclibrary的子目錄,用于分離客戶端和服務器端代碼,并為后續(xù)作為統(tǒng)一庫進行管理做準備。

在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服務器。

專業(yè)提示:使用終端時,可以通過cd 命令進入文件夾并執(zhí)行命令。假設你當前位于根目錄中,則可以使用cd .\trpclibrary命令進入trpclibrary目錄。VS Code的集成終端也同樣可以用于此操作。

為了快速初始化服務器,我們將使用 npx create-mf-app 啟動命令。該命令會生成一個預定義的項目模板,顯著節(jié)省初始設置時間。

Server-Side Setup

你可能會遇到錯誤提示,指出你沒有安裝Express或其他庫。不用擔心—你很快就會逐一安裝所有必需的庫。

成功搭建服務器后,我們將繼續(xù)使用React和相同的命令在同一個trpclibrary目錄下創(chuàng)建客戶端。

Client-Side Setup

你的React客戶端已經(jīng)準備就緒。然而,你可能會遇到與模塊和包相關的各種錯誤。因此,讓我們首先下載它們。

我正在使用yarn,我建議你也使用它。在trpcDemo根目錄下執(zhí)行yarn命令。

提示:你可以使用cd ..命令來退出當前目錄,并進入外部目錄。

你的服務器端或客戶端,亦或是兩者均可能缺少TypeScript配置文件。因此,我建議在兩個目錄下分別執(zhí)行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”命令進行安裝。

這次就不提供截圖了,你可以參考前面的步驟嘗試下載安裝。

至此,我們已經(jīng)完成了大部分安裝和設置工作。以下是你的文件夾結構應當呈現(xiàn)的外觀:

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

Folder Structure

tRPC設置

在本節(jié)中,我們將執(zhí)行以下任務:

  • 利用Context機制來創(chuàng)建tRPC實例。
  • 構建tRPC的路由系統(tǒng)并配置查詢接口。
  • 設定tRPC的基本URL地址。
  • 配置跨源資源共享(CORS)策略。

首先,在服務器端目錄的index.ts文件中創(chuàng)建一個tRPC實例,根據(jù)文檔說明,每個應用程序只應啟動一個實例。

利用該tRPC實例創(chuàng)建一個路由器。該路由器幫助你注冊路由,以便API請求到達時能夠進行處理。

路由是你處理請求并返回響應的地方。它是連接到Base URL的API端點。

例如,http://localhost:3005/api/hello這個地址描述了名為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 文件中現(xiàn)有模板代碼的上方,具體位置應在所有import語句之后,且位于聲明app和port變量聲明之前。同時,該代碼段應位于express 模塊的導入語句之下。

看!我使用了@trpc/server包中的initTRPC函數(shù)成功創(chuàng)建了一個tRPC實例。我們將依托此實例,來處理與后端相關的所有操作事務。

此外,我在tRPC路由器中添加了一個Context。這是tRPC的一項功能。它允許你將數(shù)據(jù)庫連接和身份驗證信息等詳細資料輸入其中。

tRPC能夠在所有tRPC過程之間共享Context。它作為一個信息存儲和傳遞的場所,有助于避免代碼冗余,并保持代碼的整潔有序。 到目前為止,你已經(jīng)使用了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庫,同時,你還創(chuàng)建了一個名為hello的API端點,該端點通過使用input()方法接受輸入,并將用戶的API請求與此端點定義的Zod對象進行匹配。

通過這段代碼,Zod和tRPC都期望前端傳遞的對象中包含一個基于字符串的名為name的屬性。

你獲取輸入,對其進行解構,并在query()方法中對其進行處理。這些操作都是tRPC流程的一部分。在tRPC的流程之間,Context會被共享。

正如我之前所述,你將在任何地方都需要tRPC實例。我用它來創(chuàng)建一個路由器來存儲和注冊路由(API端點),并對其進行處理。

在router()過程中,你可以創(chuàng)建無限數(shù)量的路由。它類似于一個路由處理程序,每個端點都是一個對象,每個路由都作為一個屬性存在。

你將要求過程構建器提供對query()、input()等過程的訪問權限。

現(xiàn)在,是時候配置 Base URL了。在此階段,你將使用@trpc/server庫中的Express適配器來設置 Base URL。

將以下代碼放在index.ts文件中,具體位置應在app.get()路由處理函數(shù)之前:

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

/api表示你的 Base URL。所有路由均位于/api URL之上。目前,你的hello API端點已配置為http://localhost:3005/api/hello。

接下來,讓我們嘗試使用瀏覽器進行測試。你是否還記得我曾要求你在tRPC Demo根目錄下創(chuàng)建一個包含預設代碼的package.json文件嗎?

該文件旨在實現(xiàn)服務器端和客戶端的庫式一體化運行。請將終端切換至根目錄,并執(zhí)行yarn start命令以啟動服務器和客戶端。啟動完成后,請訪問網(wǎng)址http://localhost:3005/api/hello。

tRPC Invalid Type Error

你是否遇到了錯誤提示?如果提示顯示為“無效類型”,那么你走在正確的道路上。看,這就是tRPC為我們提供的幫助所在。

在上面的代碼中,當我以用戶身份向hello API端點發(fā)送API請求時,我沒有傳遞tRPC期望該端點的任何對象或值。

tRPC期望的是一個包含一個基于字符串的屬性名為name的對象,并且需要為其提供一個值。當我沒有提供它時,tRPC就會限制我的訪問權限。這正是tRPC的出色之處。

“這一切都很好,但是現(xiàn)在怎么辦?”你必須將前端與服務器端連接起來,以便發(fā)送包含預期數(shù)據(jù)的對象。

至于服務器端,還有一件事情需要注意,那就是CORS(跨源資源共享)!設置CORS非常簡單。請在index.ts文件中找到Express框架的初始化代碼,這個代碼是Express模板自帶的。然后,在該代碼中插入以下代碼行:

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

在你的index.ts文件中,請仔細查找有關端口設置與應用配置變量的聲明部分。

一旦添加相關代碼行,可能會出現(xiàn)錯誤提示,那是因為你尚未安裝CORS的類型定義。請前往終端并在服務器端目錄下安裝@types/cors。

@types/cors download.

CORS已準備就緒且安全。服務器端已搭建完畢!現(xiàn)在,讓我們嘗試使用各自的庫來實現(xiàn)服務器端和客戶端的連接。

在我們轉向客戶端之前,我需確定我們在同一個頁面上。到目前為止,你已經(jīng)創(chuàng)建了一個tRPC實例,形成了一個路由器,設定了基本URL,并通過可選的Context對API端點進行測試。

以上所有配置和代碼均已在服務器端的index.ts文件中完成。讓我們轉到客戶端并攻克本教程的最后一部分。

客戶端

我們已經(jīng)下載了所需的包。接下來,我們將在客戶端目錄下的/src子目錄中創(chuàng)建一個trpc.ts文件。該文件將負責處理前端發(fā)出的查詢和請求。

在服務器端,你已經(jīng)創(chuàng)建了一個 tRPC 實例來構建路由器和其他組件?,F(xiàn)在,你需要在客戶端進行相同的操作。為此,你需要使用@trpc/react-query來創(chuàng)建一個客戶端 tRPC 實例。

此外,為了將客戶端 tRPC 實例與服務器端實例相連接,你必須導入服務器端的 tRPC 實例及其類型定義。

要導入服務器端 tRPC 實例,請在服務器端的package.json文件中添加一個main 屬性。這樣,當你在客戶端導入服務器端文件夾時,它將自動將index.ts文件設置為入口點。

Server-Side package.json file.

設置該屬性后,你便可以通過終端將tRPC實例導入客戶端。對我來說,在我的package.json文件中,位于服務器端目錄下的后端模塊稱為server-side,版本為1.0.0。

因此,我將在客戶端終端中執(zhí)行yarn add server-side@1.0.0命令。這一安裝過程可能看起來頗為熟悉,因為它正是開發(fā)者構建庫的常規(guī)方式。

此命令應將你的服務器端文件夾作為包添加至客戶端節(jié)點模塊目錄中。你可以通過查看客戶端的package.json文件來驗證這一點。

Client-Side package.json file.

它應當將你的服務器端包名列為依賴項。

換句話說,你已經(jīng)在客戶端應用程序中安裝了服務器端包。現(xiàn)在,你可以導入服務器端tRPC,并將其作為庫來使用。

回想之前,我們在服務器端創(chuàng)建路由器時,特意添加了額外的導出AppRout類型語句。我們之所以這么做,是因為必須在客戶端導入AppRouter類型,這樣才能在客戶端使用服務器端的tRPC實例。

以下是trpc.ts文件目前的代碼結構:

import { createTRPCReact } from 
"@trpc/react-query";
import type { AppRouter } from "server-side";

export const trpc = createTRPCReact();

trpc.ts file.

使用此代碼,你已經(jīng)利用了服務器端tRPC實例的特征成功的構建了客戶端tRPC實例。

接下來,我們將在/src目錄下創(chuàng)建一個名為AppComponent.tsx的新文件。

該文件將負責存放主應用組件,它將從trpc.ts文件中導入tRPC客戶端實例,并利用該實例調用hello API端點。

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

AppComponent.tsx import statements.

鑒于你已經(jīng)成功創(chuàng)建了tRPC客戶端實例,你現(xiàn)在可以訪問該客戶端的全部API端口,并利用useQuery( )方法向這些API端口發(fā)起請求。

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的參數(shù)不匹配問題。

在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 Statements
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.scss";
// Add the following Import Statements
import { useState } from "react";
import { trpc } from "./trpc";
import { httpBatchLink } from "@trpc/client";
import AppComponent from "./AppComponent";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

你將逐一使用每個導入語句,無需擔心關于未使用導入對象的錯誤。接著,仿照tRPC的做法,創(chuàng)建一個React Query客戶端實例。

const client = new QueryClient();

完成此操作后,你需要設置Base URL。這一步驟將在主應用程序的功能部分進行。

此外,請將位于App函數(shù)下的代碼語句移至React Query客戶端聲明語句之后,放置在App函數(shù)的頂部位置。

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

然后,你需要從App函數(shù)中移除默認的JSX超文本標記語言代碼。你可以放心地安全刪除App函數(shù)中的所有超文本標記語言內(nèi)容。

接下來,你需要為客戶端設置Base URL。每當前端進行API端點調用時,都會使用這個Base URL。它應該與你在服務器端設置的Base URL保持一致。

請將App功能代碼從HTML中替換為以下Base URL代碼:

const App = () => {
const [trpcClient] = useState(() =>
trpc.createClient({
links: [
httpBatchLink({
// Base URL
url: "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 URL
url: "http://localhost:3005/api",
}),
],
})
);
return <>;};
root.render();

我尚未詳細探討return語句的具體用法。所以,就讓我們現(xiàn)在來進行這項討論。我們不允許return語句為空。

該語句將顯示API端點返回的數(shù)據(jù),這些數(shù)據(jù)應是通過在AppComponent.tsx組件文件中調用useQuery( )方法提交的字符串。

return語句主要供包裝器及AppComponent 組件使用。若組件和頁面需要采用 tRPC、React Query 等技術,則必須使用這些庫的 Providers 來打包 AppComponent 組件。

return (
// tRPC Provider

{/* React Query Provider */}

{/* HTML React Component */}

);

現(xiàn)在,你將使用React Query打包AppComponent組件,并在該文件中傳遞你通過調用QueryClient( )創(chuàng)建的React Query客戶端實例。然后,你將利用tRPC Provider打包React Query Provider。

The tRPC Provider 需要React Query客戶端和帶有Base URL的tRPC客戶端。因此,我們也將提供該信息。

一旦你傳遞了所需信息并確保代碼與我們的代碼相匹配,你就可以訪問http://localhost:3000并查看輸出。該頁面將顯示你通過hello API端點傳遞的數(shù)據(jù)。

注意:你應該在tRPC Demo目錄下運行yarn start命令,打開localhost端口以查看輸出結果。

輸出圖像

我們已經(jīng)準備就緒。tRPC允許我們從前端調用hello API端點。它優(yōu)先考慮類型安全,并采用TypeScript來避免數(shù)以百萬計的其他JavaScript可能帶來的問題。

你可以在Route處理程序中添加更多路由和API端點,比如hello。這就像給對象添加新屬性一樣簡單。tRPC就是這樣讓你的開發(fā)工作變得更加輕松。

結論

tRPC是一個類型安全的RPC樣式庫。它將RPC與TypeScript深度集成,旨在消除REST、fetch( )和其他創(chuàng)建和調用API的技術所帶來的問題。

它作為REST和Fetch的替代方案。我將在可預見的未來繼續(xù)使用它。

譯者介紹

劉濤,51CTO社區(qū)編輯,某大型央企系統(tǒng)上線檢測管控負責人。

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

責任編輯:姜華 來源: 51CTO
相關推薦

2010-03-18 10:45:33

Python Djan

2024-11-13 15:15:46

2010-06-24 17:14:16

Linux chkco

2011-07-22 12:22:49

室內(nèi)光纜

2025-02-14 08:56:09

GoroutineContextChannel

2010-06-07 13:51:59

Hadoop簡介

2010-06-17 12:48:08

UML用例模型

2010-05-25 10:08:29

SVN權限管理

2011-08-03 10:49:15

光纖光互連

2009-04-28 10:03:35

PHPcURL抓取網(wǎng)頁

2011-08-01 23:08:33

MySQL存儲引擎

2010-06-07 16:22:55

MySQL數(shù)據(jù)庫

2010-12-08 09:38:43

C#枚舉

2009-12-25 17:32:16

ADO Data 控件

2022-12-08 10:40:06

聲明式事務AOP

2015-03-21 06:41:50

oauth2.0監(jiān)控寶

2020-12-16 10:20:15

Arrow Python 時間序列

2017-03-20 18:03:51

2011-03-01 13:59:43

結構化

2024-06-24 08:36:54

點贊
收藏

51CTO技術棧公眾號