はじめに
Firebase Hostingでデプロイ先のプロジェクト(開発、ステージング、本番)ごとにinitializeAppに渡すFirebaseの環境情報を簡単に切り替える方法はないか調査して、FirebaseのHostingのinit.jsを読み込む方法を試してみました。
FirebaseのHostingのmodule形式でないサンプルで、下記のように、init.jsが読み込まれている行が見つかります。
<script defer src="/__/firebase/init.js?useEmulator=true"></script>
中身はこんな感じです。
if (typeof firebase === 'undefined') throw new Error('hosting/init-error: Firebase SDK not detected. You must include it before /__/firebase/init.js');
firebase.initializeApp({
"apiKey": "{API Key}",
"appId": "{App ID}",
"authDomain": "{domain}",
"databaseURL": "",
"projectId": "{projectId}",
"storageBucket": "{Storage Bucket Domain}"
});
initializeApp
に渡しているJavascript Object部分を抜き出せば、コードがデプロイされているFirebaseのHosting情報を実行時に取得することができます。
コード
init.jsの中身を読み込み、正規表現で欲しい部分を抜き出し、JSON.parseを使ってJavascript ObjectとしてresolveするPromiseを使って実現しました。
let config;
export function loadFirebaseConfig() {
return new Promise((resolve, reject) => {
if (!config) {
const client = new XMLHttpRequest();
client.open('GET', '/__/firebase/init.js');
client.onreadystatechange = async function () {
if (client.readyState === XMLHttpRequest.DONE) {
const status = client.status;
if (status === 0 || (status >= 200 && status < 400)) {
const content = client.responseText;
const regex = new RegExp('.+({.+projectId.+?}).+', 'gs');
const match = regex.exec(content);
if (match) {
config = JSON.parse(match[1]);
resolve(config);
} else {
reject(new Error("Could not load/parse firebase config file."));
}
} else {
reject(new Error("The server didn't return proper response. Could not load firebase config file."));
}
}
}
client.send();
} else {
resolve(config);
}
});
}
こんな感じで使います。
import { initializeApp } from "firebase/app";
import { loadFirebaseConfig } from "loadFirebaseConfigを定義したjsのパス";
const config = await loadFirebaseConfig();
const app = initializeApp(config);
長所
- .envなどに環境情報を定義してデプロイ実行時に変更するよりは、デプロイの仕組みが単純になる。
短所
- 実行時に環境情報をhttpアクセスで取得するので、非効率。
- Firebase Hostingでしか使えない。
- 公式の方法ではないので、いつ使えなくなるかわからない。
コメント