FirebaseをStaging環境とかDebug環境とかRelease環境で切り替えをする(Webアプリ編)

この記事は [Firebase Advent Calendar 2016](http://qiita.com/advent-calendar/2016/firebase) 2日目です。

## はじめに

先日、プライベートで["Last Activity"](https://last-activity-24877.firebaseapp.com)というWebサービスをFirebaseで開発＆公開しました。その際に一番苦労した開発環境 / 検証環境 / 本番環境の切り替えについてまとめようと思います。

本記事はSPA(Single Page Application)などのWebアプリ開発を想定しています。
iOSでの開発であれば下記の記事が参考になるかと思います。
[FirebaseをStaging環境とかDebug環境とかRelease環境で切り替えをする](http://qiita.com/nnsnodnb/items/7fdd4fe934351df341e0)

## Firebaseの開発環境(Develop/Debug)と本番環境(Release)

これは特に難しいところはありません。公式が提供する[Firebase CLI](https://firebase.google.com/docs/cli/?hl=ja)を利用すればOKです。

コンソールにて`firebase serve`を実行すれば、開発機上でコードを実行でき、ブラウザから http://localhost:5000/ へアクセスすれば動作を確認することができます。

そして`firebase deploy`を実行すれば、本番環境へコードがプッシュされ、自動でデプロイされます。いや～、便利ですね！

## Firebaseの検証環境(Staging)

基本的な考え方としては「Firebase Consoleにて検証環境として新しいプロジェクトを作成し、必要に応じて`firebase use --add`で切り替える」となります。
詳細は公式ドキュメント(和訳)がありますので、そちらをご覧ください。
[Firebase Hosting での複数環境へのデプロイ](https://googledevjp.blogspot.jp/2016/08/firebase-hosting.html)

## 課題

これで万事OK！…ではありません。実は上記公式ブログで紹介されている方法には一つ罠があります。
それは「Firebase Hosting **だけ** を使うなら上記でOKだが、Realtime Databaseを使っている場合それは本番環境の方を参照してしまう」点です。

開発の初期段階で以下のようなコードをFirebase Consoleから取得したことを思い出してください。

```html
<script src="https://www.gstatic.com/firebasejs/3.6.1/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "abcdefghijklmnopqrstuvwxyz1234567890ABC",
    authDomain: "YOUR-PROJECT-NAME.firebaseapp.com",
    databaseURL: "https://YOUR-PROJECT-NAME.firebaseio.com",
    storageBucket: "YOUR-PROJECT-NAME.appspot.com",
    messagingSenderId: "999999999999"
  };
  firebase.initializeApp(config);
</script>
```

ここでdatabaseURLを定義しているため、これを書き換えない限り、たとえ検証環境にデプロイされたコードが実行されていたとしても本番環境のDatabaseを参照しにいくのは道理です。
同じ理由でおそらくStorageも同様です。※未検証

## 解決策

上記問題について公式で解決策を用意してほしいところですが、とりあえず今どうにかする必要があります。私はそれにwebpackを利用しました。

webpackの概要、インストール方法等については下記ページをご覧ください。
[webpack で始めるイマドキのフロントエンド開発](http://qiita.com/yosisa/items/61cfd3ede598e194813b)

さて、本題です。

```js:firebase.js
// Initialize Firebase
module.exports = {
  apiKey: __FB_API_KEY__,
  authDomain: __FB_AUTH_DOMAIN__,
  databaseURL: __FB_DATABASE_URL__,
  storageBucket: __FB_STORAGE_BUCKET__,
  messagingSenderId: __FB_MESSAGING_SENDER_ID__
};
```

環境によって変化する設定値をパラメータ化します。

```js:_entry.js
// Initialize Firebase
var fbConfig = require('firebase.js');
firebase.initializeApp(fbConfig);
```

```js:webpack.config.js
var webpack = require("webpack")
const path = require("path")

if (process.env.ENV == "prod") {
  // 本番環境の設定値
  FB_API_KEY = "abcdefghijklmnopqrstuvwxyz1234567890ABC";
  FB_AUTH_DOMAIN = "YOUR-PROJECT-NAME.firebaseapp.com";
  FB_DATABASE_URL = "https://YOUR-PROJECT-NAME.firebaseio.com";
  FB_STORAGE_BUCKET = "YOUR-PROJECT-NAME.appspot.com";
  FB_MESSAGING_SENDER_ID = "999999999999";
} else {
  // 検証環境の設定値
  FB_API_KEY = "lmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN";
  FB_AUTH_DOMAIN = "YOUR-PROJECT-STAGING.firebaseapp.com";
  FB_DATABASE_URL = "https://YOUR-PROJECT-STAGING.firebaseio.com";
  FB_STORAGE_BUCKET = "YOUR-PROJECT-STAGING.appspot.com";
  FB_MESSAGING_SENDER_ID = "000000000000";
}

module.exports = {
    entry: path.join(__dirname, "src", "_entry.js"),
    output: {
      path: path.join(__dirname, "public", "js"),
      filename: "app.js"
    },
    plugins: [
        new webpack.DefinePlugin({
          __FB_API_KEY__: JSON.stringify(FB_API_KEY),
          __FB_AUTH_DOMAIN__: JSON.stringify(FB_AUTH_DOMAIN),
          __FB_DATABASE_URL__: JSON.stringify(FB_DATABASE_URL),
          __FB_STORAGE_BUCKET__: JSON.stringify(FB_STORAGE_BUCKET),
          __FB_MESSAGING_SENDER_ID__: JSON.stringify(FB_MESSAGING_SENDER_ID)
        })
    ]
}
```

環境変数によって設定値を切り替えます。この方法は下記ページを参考にさせてもらいました。
[Webpackを使ってJSでも.envしたい](http://qiita.com/mikakane/items/5ab96c4c7e187ab6c9f1)

### 開発時

コードを修正したら動作確認前に`webpack`でビルドします。`webpack --watch`で自動的にビルドしてくれるらしいのですが、自分の環境(Bash on Ubuntu on Windows)では一回ビルドしてコマンドが終了してしまいます。なぜでしょうね？

### 検証環境デプロイ

`firebase use --add`にて検証環境を"stag"という名前で設定しているとします。
その場合、`firebase use stag; firebase deploy`で検証環境へデプロイできます。
`webpack -p`をその前に実行すればコードを最小化したうえでデプロイが可能です。


### 本番環境デプロイ

同様に本番環境を"prod"という名前で設定しておきます。
`ENV=prod webpack -p; firebase use prod; firebase deploy`で本番環境用にビルドしたコードがデプロイできます。webpackコマンドに環境変数で"prod"を渡しているのがポイントです。

### さらに楽をするために

毎回複数のコマンドを入力するのは面倒くさいし、ミスをする可能性もあります。
package.jsonにこんな感じで定義すると`npm run-script deploy`, `npm run-script deploy-prod`で実行でき、さらにいい感じになります。

```
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "deploy": "webpack -p; firebase use stag; firebase deploy",
    "deploy-prod": "ENV=prod webpack -p; firebase use prod; firebase deploy; firebase use stag; webpack"
  },
```

商用環境デプロイ後にstagへ切り戻しているところがポイントです。

## 最後に

["Last Activity"](https://last-activity-24877.firebaseapp.com)はあなたの活動記録を残すサービスです。
最後に洗車をした日、散髪した日など、手軽に記録して後で振り返りたいときはありませんか？35歳を越えるとそんなことはしょっちゅうだよ！(半ギレ
ということで喉から手が出るほど欲しかったサービスをようやく手に入れて自分は満足です。あるある！となった方はぜひ使ってみてください。<(_ _)>
![img01.png](https://qiita-image-store.s3.amazonaws.com/0/11338/3347cf76-8b8b-1768-6d44-a7f9149b68ff.png)