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](https://github.com/SimulatedGREG/electron-vue) は、ElectronでVueを使う際に、セットアップのお手伝いをしてくれるもので `vue-cli` から使うことができます。

詳しいことは、 [2017年度版 electron-vueで始めるVue.js](https://qiita.com/1ntegrale9/items/6e233f03b8cbff0b3c76) を見るといいです。


## セットアップ

```shell
$ 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サンプル](https://github.com/grpc/grpc/tree/master/examples/node)を参考に作っていきます。

```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>
```

## 動作確認
<img width="1112" alt="スクリーンショット 2018-04-15 14.43.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/62429/23e151c6-6e86-1c4a-f738-b5089804a684.png">

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

<img width="339" alt="スクリーンショット 2018-04-15 14.45.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/62429/babe5055-d8db-3570-25f8-2c63099b3916.png">

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

# まとめ
* Electronでgrpcを使うには、 `electron-rebuild` で練り込むだけ。

# 最後に

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

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