gRPC - connect - Render でwebサービスを作ってみる:local buf build for web service
背景
gRPCもRemixも触ったことがないので、触ってみたいと思います。
以前、以下の記事でVite+React構成のフロントエンドからgRPCサーバと通信をしてみました。
この時は生成済みのSDKを使っていたのですが、独自のサーバを立てたいので自分で実装したいと思います。
今回使ったコードは以下にあります。
参照情報
ELIZAサービスはプロトコルバッファのスキーマを定義しています。スキーマとは単純なファイルで、サービス・メソッド、引数・戻り値の型、を定義するものです。
syntax = "proto3"
service ElizaService {
string sentence = 1;
}
message SayRequest {
string sentence = 1;
}
message SayResponse {
string sentence = 1;
}
Buf Schema Registry(BSR)でコメントや追加のRPCなども含めたフルバージョンがあります。rpc
というのはRemote Procedure Callのことで、遠隔で関数を呼び出すことができます。スキーマは、サーバ・クライアント間の契約で、シリアライズの詳細に至るまでデータ交換の詳細を定義しています。
スキーマはコード生成により使えるようになります。サーバーではインターフェースが生成され、開発者はビジネスロジックの開発に専念できます。クライアント側ではやることはありません。開発者はクライアント関数を呼ぶだけです。コンパイル時に生成される型安全とシリアル化のために作られた型を使ってアプリケーションロジックの開発に集中できます。
生成済みSDK
以前生成済みSDKをnpm install
でインストールして使用しました。NMPレジストリのBSRでパッケージがリクエストされると、コードジェネレータを通してスキーマが実行され、すべての必要な依存関係と合わせて準備されます。
BSRに公開されたスキーマを使うConnectやgRPCサービスを使いたい場合は、npm
でパッケージをインストールし、Connect clientでサービスにアクセスするだけでよいです。生成済みSDKのドキュメントはこちらを見てください。
Localで生成する
Bufを使ってコード生成します。Googleのprotobuf compilerの代替手段であるBufとECMAScriptのコンパイラープラグインでコードを生成します。
- @bufbuild/buf - Protobufファイルをコンパイルし多くの言語向けのコードを生成します
- @bufbuild/protoc-gen-es - ProtobufファイルからTypeScriptかJavaScriptのコードを生成します
生成するコードは以下3つに依存します。
- @connectrpc/connect - クライアント・インターセプタ・エラー等のConnectを使うための基本的な機能を提供します
- @connectrpc/connect-web - Webブラウザ向けにConnectとgRPC-webプロトコルを提供します
- @bufbuild/protobuf - Protobufのシリアライズ機能などを提供します
まず以下をインストールします。
npm install --save-dev @bufbuild/buf @bufbuild/protoc-gen-es
npm install @connectrpc/connect @connectrpc/connect-web @bufbuild/protobuf
次にBufに2つのプラグインを使うように設定します。
# buf.gen.yaml defines a local generation template.
# For details, see https://buf.build/docs/configuration/v2/buf-gen-yaml
version: v2
plugins:
# This will invoke protoc-gen-es and write output to src/gen
- local: protoc-gen-es
out: src/gen
# Also generate any imported dependencies
include_imports: true
# Add more plugin options here
opt: target=ts
localプラグインを使わずにリモートプラグインを使うこともできます。リモートプラグインのbuf.gen.yamlのサンプルはconnect-es exampleを見てください。
最後にBufでELIZAスキーマを作りましょう。
npx buf generate buf.build/connectrpc/eliza
出力
生成されたファイルを見てみましょう。src/gen/connectrpc/eliza/v1/eliza_pb.ts
が作られていて、以下のサービスを定義しています。
export const ElizaService: GenService<{
say: {
methodKind: "unary";
input: typeof SayRequestSchema;
output: typeof SayResponseSchema;
},
}> = serviceDesc(file_connectrpc_eliza_v1_eliza, 0);
生成物について詳細に知りたい場合はProtobuf-ES projectを参照してください。
localファイルを使う
localで生成したファイルを使うには以下のようにパスを変更します。
- import { ElizaService } from "@buf/connectrpc_eliza.bufbuild_es/connectrpc/eliza/v1/eliza_pb";
+ import { ElizaService } from "./gen/connectrpc/eliza/v1/eliza_pb";
動作確認
前回と同じくプロジェクトでサーバーを起動します。
npm run dev
前回同様実行できました!
今回はVite+Reactの環境におけるconnectのコードジェネレートをlocalで実行できました。これで自分だけのサービスを作る時は自由に定義・ビルド・利用できそうです 👍
Discussion