この記事は 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 で始めるイマドキのフロントエンド開発
さて、本題です。
// 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__
};
環境によって変化する設定値をパラメータ化します。
// Initialize Firebase
var fbConfig = require('firebase.js');
firebase.initializeApp(fbConfig);
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歳を越えるとそんなことはしょっちゅうだよ!(半ギレ
ということで喉から手が出るほど欲しかったサービスをようやく手に入れて自分は満足です。あるある!となった方はぜひ使ってみてください。<(_ _)>