JavaScript
環境構築
SPA
Firebase
webpack

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

More than 1 year has passed since last update.

この記事は Firebase Advent Calendar 2016 2日目です。

はじめに

先日、プライベートで"Last Activity"というWebサービスをFirebaseで開発&公開しました。その際に一番苦労した開発環境 / 検証環境 / 本番環境の切り替えについてまとめようと思います。

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

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

これは特に難しいところはありません。公式が提供するFirebase CLIを利用すればOKです。

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

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

Firebaseの検証環境(Staging)

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

課題

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

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

<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 で始めるイマドキのフロントエンド開発

さて、本題です。

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__
};

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

_entry.js
// Initialize Firebase
var fbConfig = require('firebase.js');
firebase.initializeApp(fbConfig);
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したい

開発時

コードを修正したら動作確認前に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"はあなたの活動記録を残すサービスです。
最後に洗車をした日、散髪した日など、手軽に記録して後で振り返りたいときはありませんか?35歳を越えるとそんなことはしょっちゅうだよ!(半ギレ
ということで喉から手が出るほど欲しかったサービスをようやく手に入れて自分は満足です。あるある!となった方はぜひ使ってみてください。<(_ _)>
img01.png