スキップしてメイン コンテンツに移動

Firebase Hostingで取得できるinit.jsからFirebaseの環境情報を抜き出すjavascript

はじめに

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でしか使えない。
  • 公式の方法ではないので、いつ使えなくなるかわからない。

コメント