最近、話題のtRPCを試してみたので記事にしました。
tRPCとは?
- スキーマやコード生成なしで型安全なAPIの連携が行えるPRCフレームワーク
- TypeScriptに特化しており、非常にシンプルに実装できる
- 比較対象としては、GraphQLやOpenAPIなどの技術に該当するが、tRPCはBFFで使われることが前提にありそうなので単純な比較は出来なさそう
そもそもRPCとは?
- RPC ( Remote Procedure Call ) とは、ネットワークで繋がっている別のコンピュータのプログラムを実行できるようにする技術
- クライアント側からサーバー側への疎通を行う際に、具体的な通信手段やプロトコルを意識することなく、関数の呼び出しを行うことがでやり取りが行える仕組み
- Googleが開発したRPCのプロトコルなので、gRPCという命名になっている
- tRPCのtはTypeScriptを表して
学ぶモチベーション
- BFF構成で多数のマイクロサービスにアクセスするようなプロダクトの場合、BFF部分はfrontendエンジニアが管理することが多い
- その場合の選択肢としてtRPCを使うのが有効なのではないかなと考え検証
- frontend側でAPI周りを型安全にするには、OpenAPIやGraphQLを使うことが多かったが、frontendエンジニアが扱うには難易度が高い & コードジェネレートが必要なパターンが多い
- tRPCなら、コードジェネレートも不要で、frontendエンジニアでも使い慣れたTypeScriptで書けて便利そう
リポジトリ
今回で検証したコードは以下で確認できる
実装
Quickstart
公式のQuickstartを元に簡単なサーバー側の実装をしてみる。
import { createHTTPServer } from "@trpc/server/adapters/standalone"; import { initTRPC } from "@trpc/server" const t = initTRPC.create(); const appRouter = t.router({ helloWorld: t.procedure.query(() => { return "Hello World"; }), }); export type AppRouter = typeof appRouter; const server = createHTTPServer({ router: appRouter, }); server.listen(8000);
上記をtRPCを呼ぶスクリプトの実装が以下の通り
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client"; import type { AppRouter } from "./server"; const trpc = createTRPCProxyClient<AppRouter>({ links: [ httpBatchLink({ url: "http://localhost:3000", }), ], }); trpc.helloWorld.query().then((res) => { // output "Hello World" console.log(res); });
こんな感じでメソッドを呼ぶだけでAPI通信が行える。
以下みたいな感じでコードの補完もされる。
ReactでtRPCを呼ぶ
公式でHooksが提供されているので、こちらを使用して実装。
最初にProvider部分を実装。
import { useState } from "react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { httpBatchLink } from "@trpc/client"; import { trpc } from "../utils/trpc"; type Props = { children: React.ReactNode; }; function Trpc(props: Props) { const [queryClient] = useState(() => new QueryClient()); const [trpcClient] = useState(() => trpc.createClient({ links: [ httpBatchLink({ url: "http://localhost:8080", }), ], }) ); return ( <trpc.Provider client={trpcClient} queryClient={queryClient}> <QueryClientProvider client={queryClient}> {props.children} </QueryClientProvider> </trpc.Provider> ); } export default Trpc;
上記のProviderを作成すれば、以下のコードのようにメソッドを呼んでReactでも簡単にAPIの通信が実行できる。
■ Page.tsx
import { trpc } from "./utils/trpc"; export default function IndexPage() { const userQuery = trpc.helloWorld.useQuery(); return <div>{userQuery.data}</div>; }
React + tRPC + Prismaでデモを実装
- 上記のリポジトリで実装
- 簡単にコードの説明をすると以下のような感じ
- PrismaでDBの定義を行う
- tRPCとPrismaの連携
- Reactとの連携
BFFとは、少し話がズレましたが開発の体験が結構良かった
Deno + tRPCを試す
- 上記のリポジトリで実装
- モチベーション
- TypeScriptをデプロイするのが面倒だったので、Denoで行けたら1つで全て済むと思い検証
- 結果
- tRPCの実装はできるけど、Denoで実装したファイルをimportできるのはDenoのみなので、結果フロントエンドもDenoで実装する必要がある
- こうなってくると旨味が薄れるので、まだ実用段階では無さそうという結果になった
まとめ
- コードジェネートして型安全をする方法に慣れきっていたが、tRPCはコードジェネートしなくても型安全が実現できるので手軽
- TypeScript周りのツールも大分充実してきて書きやすいので、tRPCを使っていくのも全然有り
- BFFでの使用は、かなり有り。
- 手軽にtRPCを試したい場合は、以下のT3 Appを使用するのが良いと思うので、興味のある方は試してみたら良いと思います