electron / electron-vueでgRPCを使う


はじめに

Electronは、基本的に内部でChrome(Chromium)が動いていて、 Webアプリケーションをそのまま、デスクトップアプリケーションとして提供できたりします。

gRPCは、Googleが発表したRPCフレームワークです。RPCってなんだよ…。 Protocol Bufferってなんだよ…ってWebエンジニアの人とかは特に思うと思いますが gRPCは思ってるより簡単で、思ってるよりも良い物です。

今、gRPCが主に使われている部分はマイクロサービス化されたサーバ同士の通信などですが、クライアントとの通信にもどんどん使われていっています。
WebでgRPCを使うには、 grpc-gateway などを使って通信する必要があり少し残念ですが、Electronであれば問題なく使えます。

electron-vue

electron-vue は、ElectronでVueを使う際に、セットアップのお手伝いをしてくれるもので vue-cli から使うことができます。

詳しいことは、 2017年度版 electron-vueで始めるVue.js を見るといいです。

セットアップ

$ vue init simulatedgreg/electron-vue electron-vue-grpc
$ cd electron-vue-grpc
$ yarn

gRPC / electron-rebuild を追加

grpc をインストールして、 electron-rebuildでelectronにgrpcを練り込みます。
electron-rebuild はまぁまぁ長いので、気長に待ちます

$ yarn add grpc  electron-rebuild
$ ./node_modules/.bin/electron-rebuild
⠴ Building module: grpc, Completed: 0
✔ Rebuild Complete

gRPCを試してみる

簡単なgRPCのサーバを用意して、gRPCを試してみます。

サーバ

gRPC公式のNode.jsサンプルを参考に作っていきます。

helloworld.proto
syntax = "proto3";

package helloworld;

// 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;
}
server.js
const path = require('path')
const grpc = require('grpc')
const PROTO_PATH = path.join(`${__dirname}/../src/protos/`)
const helloProto = grpc.load(`${PROTO_PATH}/helloworld.proto`).helloworld

function sayHello (call, callback) {
  console.log(`Hello ${call.request.name}`)
  callback(null, { message: `Hello ${call.request.name}` })
}

function main () {
  const server = new grpc.Server()
  server.addService(helloProto.Greeter.service, { sayHello })
  server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure())
  server.start()
  console.log('Server is running')
}

main()

クライアント

最初からある LandingPage.vue に実装していきます。

まず、 gRPC Button という名前のボタンを追加します。
gRPC Button はクリックしたら sayHello メソッドを叩きに行きます。

LandingPage.vue
<div class="doc">
  <div class="title alt">Other Documentation</div>
  <button class="alt" @click="open('https://electron.atom.io/docs/')">Electron</button>
  <button class="alt" @click="open('https://vuejs.org/v2/guide/')">Vue.js</button>
  <button class="alt" @click="sayHello('エレクトロン太郎')">gRPC Button</button>
</div>

grpcをimportして、サーバと繋いでいます。
sayHello メソッドは、サーバに sayHello します。

LandinPage.vue
<script>
  import path from 'path'
  import grpc from 'grpc'
  import SystemInformation from './LandingPage/SystemInformation'

  const helloProto = grpc.load(path.join(`${__dirname}/../../protos/helloworld.proto`)).helloworld
  const client = new helloProto.Greeter('localhost:50051', grpc.credentials.createInsecure())

  export default {
    name: 'landing-page',
    components: { SystemInformation },
    methods: {
      open (link) {
        this.$electron.shell.openExternal(link)
      },
      sayHello (name) {
        client.sayHello({ name }, (err, response) => {
          alert(response.message)
          console.log(`Greeting ${response.message}`, err)
        })
      }
    }
  }
</script>

動作確認

gRPC Buttonを押すとサーバから Hello エレクトロン太郎 と返ってきてる事が確認できます。

サーバにも、ちゃんと接続されてる事が確認できます。

まとめ

  • Electronでgrpcを使うには、 electron-rebuild で練り込むだけ。

最後に

ここで紹介したコードはGithubに公開してあります。ぜひ参考にしてください。
https://github.com/satotakumi/electron-vue-grpc

たぶん、 eletron-rebuild だけ自分でやる必要はあるかも。