0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

gRPC 公式サンプルを Node.js + TypeScript on Windows (+ PowerShell) 化する

Last updated at Posted at 2020-04-08

参考

こちらの素晴らしい記事を全面的に参考にしていきます。

この記事でする事

  • 参考記事の通りに進めると、Windows と lint 由来の躓きポイントやがあります。これに対応していきます。
  • コマンドプロンプトは今後PowerShellに置き換えられていくそうなので、PowerShell前提で進めます。
  • 題材として公式サイトにあるサンプルprotoファイルを使用して、これをTypeScript対応させていきます。

下準備

適当な場所に、新規フォルダを作成し、npm 初期化から typescriptts-node のインストールまで行います。

npm init -y
npm i -D typescript ts-node

今後 src フォルダにソースを入れていくので、src フォルダも用意します。

gRPC 実装

では、gRPC 用のモジュール追加やらファイル作成していきます。
どうでも良い話ですが、ずっとgr pc を gr cp だと思っていて、いまだに間違えます。P = Protocolの印象があるからですね…

proto ファイルを作成

前述の通り公式サンプルを使用するので、以下のように proto ファイルを作成します。
今回は proto フォルダを作成してその中に hello.proto を作成しました。

syntax = "proto3";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

冒頭の syntax = "proto3"; は、公式サイトには無いのでご注意下さい。

コード生成

必要な依存関係をインストールします。

npm i -D grpc-tools grpc_tools_node_protoc_ts

参考元の記事ではここでシェルスクリプトを書くのですが、こちとら Windows なので ps1 ファイルです。
proto.ps1 というファイルを作成します。変数は必要であれば適宜変更してください。
windowsでは proto\* という記述が出来ないみたいで、とりあえず一つのファイルだけを指定しています。

今回はこれで問題ないのですが、おまけ2に複数ファイルを変換できるコマンドを記載しておきます。

$PROTO_SRC="proto\hello.proto"
$PROTO_DEST="$(pwd)\src"

npx grpc_tools_node_protoc --js_out=import_style=commonjs,binary:$PROTO_DEST  --grpc_out=$PROTO_DEST --plugin=protoc-gen-grpc=$(npm bin)/grpc_tools_node_protoc_plugin.cmd $PROTO_SRC
npx grpc_tools_node_protoc --plugin=protoc-gen-ts=$(npm bin)/protoc-gen-ts.cmd --ts_out=$PROTO_DEST $PROTO_SRC

ポイントは、コマンドに .cmd が追加されている事ですね。

これを実行します。

./proto.ps1

すると、src/proto に以下のファイルが出来ます。
proto フォルダは自動で作成するようですが、src フォルダは事前に作っておかないとエラーが出ます。

  • hello_grpc_pb.d.ts
  • hello_grpc_pb.js
  • hello_pb.d.ts
  • hello_pb.js

サーバー実装

gRPC サーバーを実装するための依存関係は以下の通りです。

npm i -D @types/google-protobuf
npm i -S grpc google-protobuf

src/app.ts を作成し、以下の内容を記述します。

import * as grpc from "grpc";
import { IGreeterServer, GreeterService } from "./proto/hello_grpc_pb";
import { HelloRequest, HelloReply } from "./proto/hello_pb";

class HelloService implements IGreeterServer {
  public sayHello(
    call: grpc.ServerUnaryCall<HelloRequest>,
    callback: grpc.sendUnaryData<HelloReply>
  ): void {
    const r = new HelloReply();
    r.setMessage("Hello " + call.request.getName());
    console.log("receive: " + call.request.getName())
    callback(null, r);
  }
}

const server = new grpc.Server();
server.bind("0.0.0.0:50051", grpc.ServerCredentials.createInsecure());
server.addService(GreeterService, new HelloService());

server.start();
console.log("server running on 0.0.0.0:50051");

いずれもタイプセーフ、lintにも引っかかりません。気持ちいい。
以下のコマンドでサーバー起動します。

npx ts-node src/app.ts

クライアント実装

同様に、クライアントも実装していきます。
src/client.ts を作成し、以下の内容を記述します。

import * as grpc from "grpc";
import { GreeterClient } from "./proto/hello_grpc_pb";
import { HelloRequest } from "./proto/hello_pb";

const client = new GreeterClient(
  "127.0.0.1:50051",
  grpc.credentials.createInsecure()
);

const req = new HelloRequest();
req.setName("John");

client.sayHello(req, function (error, result) {
  if (error) console.log("Error: ", error);
  else console.log(result.toObject());
});

こちらもタイプセーフでlintクリア。気持ちいい。
以下のコマンドで起動します。

npx ts-node src/client.ts

テスト

PowerShell のプロンプトを2つ立ち上げ、サーバー -> クライアントの順に起動します。
サーバー側に

server running on 0.0.0.0:50051
receive: John

クライアント側に

{ message: 'Hello John' }

が表示されれば成功です。

おまけ: 必要な依存パッケージまとめ

必要な依存関係が、記事中にバラバラしてしまったので、まとめておきます。

npm i -D typescript ts-node grpc-tools grpc_tools_node_protoc_ts @types/google-protobuf
npm i -S grpc google-protobuf

おまけ2: 複数のprotoファイルを変換する

前述の通り windows の PowerShell でワイルドカード指定が出来ないので、ファイル一覧を取得して一つ一つ変換するコマンドを書きました。ゴリ押しです。

$PROTO_DIR="proto"
$PROTO_DEST="$pwd\src"

$LIST=Get-ChildItem ${pwd}/$PROTO_DIR -Name -Include *.proto

function convert($FILE) {
	npx grpc_tools_node_protoc --js_out=import_style=commonjs,binary:$PROTO_DEST  --grpc_out=$PROTO_DEST --plugin=protoc-gen-grpc=$(npm bin)/grpc_tools_node_protoc_plugin.cmd $PROTO_DIR/$FILE
	npx grpc_tools_node_protoc --plugin=protoc-gen-ts=$(npm bin)/protoc-gen-ts.cmd --ts_out=$PROTO_DEST $PROTO_DIR/$FILE
}

foreach($item in $LIST) {
    convert($item); 
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?