シンプルで使いやすい新たなRPCライブラリ~oRPCとは何者か?~
はじめに
こんにちは、エンジニアの籏野です。
先日、oRPCというライブラリのV1がリリースされました。
oRPCはTypeScriptを利用するシステムにおいてRPC(Remote Procedure Call)を実現するためのライブラリです。
RPCの特徴は、クライアント側からはメソッドを呼び出すような感覚でAPIを利用することができ、REST APIのようにエンドポイントを意識する必要がなくなることが挙げられます。
RPCを実現する有名なライブラリとしてtRPCがありますが、どのような違いがあるのかが気になり調べてみました。
今回はブログに投稿されたV1発表記事を参考にどのような特徴があるのかをまとめていきます。
強力なシンプルさ
ブログではoRPCの理念として、「強力なシンプルさ(powerful simplicity)」を掲げています。
これはどういうことなのか、tRPCとoRPCでプロシージャの定義方法を見比べていきましょう。
IDを指定してユーザーを取得するプロシージャを定義する場合、tRPCでは以下のように定義します。
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const router = t.router;
export const publicProcedure = t.procedure;
import { z } from 'zod';
import { router, publicProcedure } from './trpc';
const appRouter = router({
userById: publicProcedure
.input(
z.object({
id: z.string()
})
)
.query(async (opts) => {
const { input } = opts;
// do something
return user;
}),
...
});
一方、oRPCでは以下のように定義します。
import { os } from '@orpc/server'
import { z } from 'zod'
export const getUserById = os
.input(
z.object({
id: z.string()
}),
)
.handler(async ({ input }) => {
// do something
return user;
})
export const router = {
user: {
get: getUserById,
...
}
}
作者はtRPCのセットアップの複雑さに対して課題感を掲げており、インポートしたos
というオブジェクトを利用して即座にRPCを構築できる点にこだわりを感じます。
またクライアント側での利用方法も比較しておきましょう。
tRPCの場合は以下のようになります。
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from './server';
const trpc = createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: 'http://localhost:3000',
}),
],
});
trpc.userById(...)
oRPCの場合は以下のようになり、ここについては大きな違いはなく同じような使用感で利用できそうです。
import type { RouterClient } from '@orpc/server'
import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
const link = new RPCLink({
url: 'http://127.0.0.1:3000',
})
export const orpc: RouterClient<typeof router> = createORPCClient(link);
orpc.user.get(...)
OpenAPIサポート
ブログではOpenAPIのサポートも大きな特徴として挙げています。
tRPCでもtrpc-openapiを利用することでOpenAPIサポートが可能でしたが、このライブラリは現在メンテナンスされていません。
oRPCでは以下のようにOpenAPIHandler
を利用することですぐにOpenAPI定義を生成可能です。
import { OpenAPIHandler } from "@orpc/openapi/node";
import { CORSPlugin } from "@orpc/server/plugins";
const handler = new OpenAPIHandler(router, {
plugins: [new CORSPlugin()],
});
ベンチマーク
oRPCとtRPCを比較したベンチマークも示されており、以下のような結果となっています。
評価項目 | oRPC | tRPC | 改善率 |
---|---|---|---|
型チェック速度 | 5.9秒 | 9.3秒 | 1.6倍高速 |
ランタイム性能 | 295,000リクエスト/20秒 | 104,000リクエスト/20秒 | 2.8倍高速 |
最大CPU使用率 | 102% | 129% | 1.26倍低減 |
最大RAM使用量 | 103MB | 268MB | 2.6倍低減 |
バンドルサイズ | 32.3kB | 65.5kB | 2倍小型化 |
まとめ
ドキュメントを見てみると分かるのですが、oRPCは非常に多くの機能を持っておりこの記事で挙げたもの以外にも様々なポイントを推しだしています。
- End-to-End Type Safety
- First-Class OpenAPI
- Contract-First Development
- Framework Integrations
- Server Actions
- Standard Schema Support
- Native Types
- Lazy Router
- SSE & Streaming
- Multi-Runtime Support
- Extendability
- Reliability
またドキュメントの「Integrations」の欄を見ると、Next.js/Honoなど様々なフレームワーク上で動かせるのも個人的には嬉しいポイントであると感じています。
今後のAPI構築の際の選択肢として、大きく発展していくことを期待しています。
この記事を書いた人
籏野 拓
2018年新卒入社
Discussion