https://qiita.com/teyosh/items/58c637cc8bb8b161712d

More than 1 year has passed since last update.

こんにちは。こちらはトレタ Advent Calendar 2019 22日の記事です。(大幅遅刻で申し訳ありません) トレタでは積極的にgRPCを採用しています。そこでgrpc-webを利用するための準備をまとめました。

gRPCとブラウザの関係

現在2019/12時点ではウェブブラウザではgRPCで通信することはできません。 そのため、gRPCとhttpを変換するための機構が必要となります。 候補として2つあり、 ・ gRPCサービスにRestful-APIのリバースプロキシを追加するgrpc-gateway ・ http上でbinaryもしくはbase64encodeしたデータを送信して、envoyなどのproxyでgRPCに変換するgrpc-web

grpc-webとjavascript

grpc-webはgRPC for Web Clientsと謳われているようにgRPC自体をweb clientで扱うためにあります。 gRPCで利用されるデータのインターフェース構造はprotocol buffersで設定します。 protocol buffersはIDLのため各種言語用に変換をしなくてはいけません。

protocとprotoc-gen-grpc-web

protocol buffersを変換するためのprotocとgrpc-web用に生成するためのプラグインprotoc-gen-grpc-webを利用します。 こちら両方とも実行ファイルのためプラットフォーム別にファイルが異なっているので、管理上dockerで生成すると便利だと思います。

FROM node:12-buster

ARG APP_HOME=${APP_HOME:-/app}
RUN mkdir -p $APP_HOME

ARG GRPC_HOME=${GRPC_HOME:-/grpc}
RUN mkdir -p $GRPC_HOME
WORKDIR $GRPC_HOME

USER root

RUN npm i rimraf -g
RUN curl -L -O <https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protoc-3.11.2-linux-x86_64.zip>
RUN curl -L -O <https://github.com/grpc/grpc-web/releases/download/1.0.7/protoc-gen-grpc-web-1.0.7-linux-x86_64>
RUN unzip protoc-3.11.2-linux-x86_64.zip && cp ./bin/protoc /usr/local/bin/. && chmod +x /usr/local/bin/protoc
RUN cp protoc-gen-grpc-web-1.0.7-linux-x86_64 /usr/local/bin/protoc-gen-grpc-web && chmod +x /usr/local/bin/protoc-gen-grpc-web

WORKDIR $APP_HOME

protocのdockerをdocker-composeから利用します。

version: '3.7'
services:
  protoc:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - type: bind
        source: ./
        target: /app
    command: bash -c 'npm run protoc'

プロジェクトrootをbindしてnpmで実行するようにpackage.jsonにscriptを作成します。

"scripts": {
    "protoc": "npx rimraf ./grpc && mkdir -p ./grpc && cd ./proto && protoc *.proto -I. --js_out=import_style=commonjs:../grpc --grpc-web_out=import_style=typescript,mode=grpcwebtext:../grpc"}

protocol buffersをprotoディレクトリに用意します、

syntax = "proto3";

message HelloRequest { string world = 1; }
message HelloResponse { string world = 1; }

service HelloService { rpc World(HelloRequest) returns (HelloResponse); }

これでdocker-compose run protocと実行すればgrpcディレクトリにjavascriptとtypescriptのファイルが生成されます。

.
├── Dockerfile
├── docker-compose.yml
├── grpc
│   ├── HelloServiceClientPb.ts
│   ├── hello_pb.d.ts
│   └── hello_pb.js
├── index.ts
├── node_modules
│   └── grpc-web
│       ├── README.md
│       ├── index.d.ts
│       ├── index.js
│       └── package.json
├── package-lock.json
├── package.json
└── proto
    └── hello.proto

まずはgrpc-webをインストールします。