Vue.jsの開発環境とngrokを連携する方法

# はじめに

Vue.jsでFacebookログインとGoogleログインを開発をしていて、開発環境でHTTPSが必要でした。
実際は、[こちらの記事](https://qiita.com/idani/items/ceb0662cc30a43ec6cac)で書いた通り、「yarn serve --https」で事足りました。

しかし、開発中は、それに気づかずに、[ngrok](https://ngrok.com/)の連携までして開発を行いました。
結構がんばったので記事にしました(笑)

[ngrok](https://ngrok.com/)を使う上での困ったところは、起動するたびに公開URLが変わってしまうことです。
このため都度都度vue.jsのdevserverの設定を変更する必要があります。
そのあたりを**極力**自動化するようにしました。

デモ用にアプリを外部公開するとかに使えるので、お試しください。

# TL;DR

* ngrokの起動スクリプト([ngrok.js](https://github.com/idani/vue-ngrok-sample/blob/master/ngrok.js))を作成した。
* [ngrok.js](https://github.com/idani/vue-ngrok-sample/blob/master/ngrok.js)を実行すると、ngrokを実行し、転送先の公開URLと転送元のポート番号を「process.env.NGROK_FILE」に書き出す
* その後、「yarn serve」をすると、「process.env.NGROK_FILE」ファイルを読み込んで適切な状態で開発サーバを起動します。
 * [vue.config.js](https://github.com/idani/vue-ngrok-sample/blob/master/vue.config.js)ファイルを修正した

以上をまとめたサンプルプロジェクトを作成しましたので、こちらをご覧ください。
https://github.com/idani/vue-ngrok-sample

![2018-10-07_18h05_06](https://user-images.githubusercontent.com/1624829/46580567-39323e80-ca62-11e8-817a-bad64171b129.gif)

それでは、詳細説明の始まり。。。

# 今回の課題

* 開発サーバにngrokから提供される公開URLを設定する必要がある。
 * 「[WebpackDevServer で建てたサーバーが ngrok から見れない時](https://qiita.com/nju33/items/c0743acd327dd3345607)」のような設定をする必要がある
* vue-cli-service serve --public xxxxxx.ngrok.io としたら、いい感じに動きそうで、動かなかった。。。
 * vue.config.jsに設定すると動いた！ 

# 目標

* ngrokを起動して、取得した公開URLをvue.config に自動設定してdevserverが起動したい！

# 実現方法

* [ngrokはnpmパッケージにあった](https://www.npmjs.com/package/ngrok)ので連携が可能
* 「vue-cli-service　serve」を子プロセスで起動すると面倒くさい感じだったので、「ngrokを制御するスクリプト」と「vue-cli-service　serve」は、公開URLなどをファイルで共有する疎結合とした。


# 準備

## [ngrok](https://ngrok.com/)のアカウント作成

**アカウントをお持ちの方はスキップしてください。**
[ngrok](https://ngrok.com/)のサイトで登録してください。

## Authトークンを取得する

**取得済みの方はスキップしてください。**
**ngrokのダウンロードファイルはnpmパッケージで入れますので不要です！**


[ngrok](https://ngrok.com/)にログイン後、以下の画像の箇所でAuthトークンが取得ができます。
![2018-10-07_19h02_58.png](https://qiita-image-store.s3.amazonaws.com/0/133291/f925797d-7b81-49ef-ab48-5922f649764b.png)


# Vue.jsのプロジェクトを作成する

```shell
vue ui
```

# ngrok, env-cmd を追加する
```shell
yarn add ngrok env-cmd --dev
```
* ngrokは今回の主役で、JSで操作するために必要。
* env-cmdは、vue-cli-serviceがデフォルトで使用する環境変数ファイルの「.env」ファイルの設定を独自スクリプトで読み込むために使います。


# ngrokのAuthトークンを設定するスクリプトを実行する

ここかはらサンプルソースを用意していますので、適宜Git Cloneしてみてください。
https://github.com/idani/vue-ngrok-sample

**ngrokのAuthトークンの設定が完了している方は、スキップしてください**

「[ngrok_auth.js](https://github.com/idani/vue-ngrok-sample/blob/master/ngrok_auth.js)」というファイル名で以下のスクリプトをプロジェクト直下なり、好きな場所に作成します。
※[サンプルプロジェクト](https://github.com/idani/vue-ngrok-sample)にも取り込んであるので、ダウンロードして使ってください。

この時に、「YOUR_TUNNEL_AUTHTOKEN」という箇所を取得したAuthトークンに書き換えます。

```javascript:ngrok_auth.js

const ngrok = require('ngrok');
(async () => {
    await ngrok.authtoken('YOUR_TUNNEL_AUTHTOKEN')
})
```
そして、コマンドラインで実行します。

```shell
node ngrok_auth.js
```

すると以下の設定ファイルが作成されます。

```shell
OS X	/Users/example/.ngrok2/ngrok.yml
Linux	/home/example/.ngrok2/ngrok.yml
Windows	C:\Users\example\.ngrok2\ngrok.yml
```

# [ngrok.js](https://github.com/idani/vue-ngrok-sample/blob/master/ngrok.js)(ngrokを起動するスクリプト)

ngrokを起動する、「[ngrok.js](https://github.com/idani/vue-ngrok-sample/blob/master/ngrok.js)」という以下のファイルを作成しました(リンク先参照)。

* ngrokを起動後、転送先のURLと転送元のローカルポートを「NGROK_FILE」ファイルに書き出す処理をします。
* Ctrl-Cで終了時に、「NGROK_FILE」を削除します。
* 「NGROK_FILE」は環境変数から読み込みます。vue-cliの環境変数と統一するため、.envファイルに環境変数を設定しました。この.envファイルを環境変数に設定するために**env-cmd**を利用しています。

```shell
env-cmd .env node ngrok.js
```
として利用します。

pakcage.jsonに以下のように追記しました。

```json:pckage.json
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "ngrok": "env-cmd .env node ngrok.js", <-これ
    "ngrok_add_authtoken": "node ngrok_auth.js"
  },
```


# [vue.config.js](https://github.com/idani/vue-ngrok-sample/blob/master/vue.config.js)


[vue.config.js](https://github.com/idani/vue-ngrok-sample/blob/master/vue.config.js)で開発サーバの設定ができます。
https://cli.vuejs.org/config/#devserver

```javascript
const path = require('path')
const fs = require('fs')

// ngrokで取得したURLを共有するファイル
const hostFile = path.resolve(process.env.NGROK_FILE)

let publicHost = ''
let port = '8080'
try {
  const data = fs.readFileSync(hostFile, 'utf8')
  if (data) {
    publicHost = data.replace(/^https:\/\//, '').replace(/:\d+$/, '')
    port = data.replace(/^.*:/, '')
  }
} catch (error) {
  // ファイルがない場合のエラーはキャッチするが、ない場合はない場合で、そのまま処理を進めるため、無視していく
  // console.log(error)
}

module.exports = {
  devServer: {
    public: publicHost,
    port: port
  }
}
```

* 環境変数「NGROK_FILE」を読み込みます。読めない場合はスルーして、通常の設定で起動します。
* 読み込んだファイルから、公開URLとポートを取得します。

# 使い方

1. ターミナルを２つ開きます
2. **yarn ngrok** を起動して、公開URLが表示されるのを待つ
3. 公開URLが表示後、**yarn serve**を実行

![2018-10-07_18h05_06](https://user-images.githubusercontent.com/1624829/46580567-39323e80-ca62-11e8-817a-bad64171b129.gif)


# その他（いいわけ）

* Googleログインは、HTTPSとか不要なので、あまり悩まず開発した。
* 続けてFacebookログインを開発するにあたって、HTTPSが必要なので、[Vue.jsの開発をlocalhostでHTTPS環境で行う方法](https://qiita.com/idani/items/ceb0662cc30a43ec6cac)を見つけた
* そしたらHTTPS環境だと、GAPIがドメインが未登録なので使えませんよってエラーをだした(汗)
* ngrokで開発しないとダメじゃんってことで、こちらの記事のことを実行した。
* 大変だったのQIITAにまとめていたら、Googleログインも普通に動いた(汗)
 * 開発中に、GAPIに関連して、Google+APIの利用を許可しないさいというメッセージがでたので、許可をしたのですが、それで動くようになったかも？

# 参考URL

* [Facebookログインがhttps必須になったので、localhost開発でも対応する](https://qiita.com/kent_ear/items/6fcc477392aaede175f4)
* https://www.npmjs.com/package/ngrok
* https://cli.vuejs.org/config/#devserver
* [WebpackDevServer で建てたサーバーが ngrok から見れない時](https://qiita.com/nju33/items/c0743acd327dd3345607)