LoginSignup
3
4

More than 3 years have passed since last update.

Firebaseの設定ファイルをプロジェクト毎に動的に生成する(Expo/React Nativeほか)

Last updated at Posted at 2019-12-12

React Nativeのアプリの結合テスト環境を作りたいのですが、そのためには開発用・テスト用・本番用など、複数のFirebaseプロジェクトを容易に切り替えられるような仕組みが欲しいところです。
そこで、
webpackでfirebaseのconfigファイルをプロジェクト毎に動的に生成する(環境切り替えに使える)
こちらの記事を参考にしながら、Firebaseの設定ファイルを動的に生成してみたいと思います。

上記の記事ではWebpackの独自loaderを作って設定ファイルを差し替えていますが、Expoで作成しているアプリなど、モジュールバンドラの設定を変更できない場合もありますので、loaderで直接Webpack等に渡すのではなく、設定ファイル自体を生成してしまって、.gitignoreに追加するという方針でやってみます。

切り替えるプロジェクトの情報を用意

$ firebase login
$ firebase init

は、すでに済んでいるでしょうから、.firebasercプロジェクトエイリアスの情報があるはずです。

{
  "projects": {
    "default": "some-default-project",
    "test": "some-test-project"
  }
}

なんでもいいですが、こんな感じでデフォルトはこのプロジェクト、テスト用はこのプロジェクト、というエイリアスを登録します。これは直接.firebasercを編集するでもいいし、

$ firebase use --add

で追加するのでもいいです。
.firebasercをリポジトリ上に公開するかどうかは場合によるでしょうが、公開しない場合、かつ必要なエイリアスを明示したい場合は.firebaserc-exampleなどを置いてもいいかと思います。

設定ファイルを取得するスクリプトを作成

ローカルにfirebase-toolsをインストールします。

$ npm install --save-dev firebase-tools

これをコマンドを直接叩くのではなくJSファイルで使います。
コマンドの挙動はnode_modules/firebase-tools/lib/commandsを直接見るか、
公式の簡易的なリファレンスで確認してください。

では、ここで元の記事で使用しているsetup:webを使いたいのですが、どうやら公式リファレンスを見るとこのコマンドは非推奨とされているようです。
なのでリファレンスに書いてある通り、apps:sdkconfigを使用してみます。

このコマンドで生成できる設定ファイルはJSONではなくglobal変数にfirebaseがある前提のJSファイルという面倒な代物なので(後ほど記載)、正直なところsetup:webを使ってしまった方がいいと思いますが、我慢します。

まず、そもそもReact NativeアプリはFirebaseにとってはWebアプリということでいいのかという疑問もあります。
少なくともExpoで開発しているときはWebアプリとして扱い、ejectしたりした後はiOS/Androidそれぞれという感じかと思っています。

さて、scriptsディレクトリを作り、Node.jsの世界で動く以下のようなJSを書きます。

scripts/setFirebaseConfig.js
const fs = require('fs');
const firebaseTools = require('firebase-tools');

(async () => {
  try {
    const firebaseRC = JSON.parse(fs.readFileSync('./.firebaserc'));
    const projectId = firebaseRC.projects[process.argv[2]];
    await firebaseTools.use(projectId, {});
    const apps = await firebaseTools.apps.list('WEB', {});
    const currentApp = apps[0];
    const config = await firebaseTools.apps.sdkconfig('WEB', currentApp.appId, {});
    fs.writeFileSync('./js/firebaseConfig.js', config.fileContents);
    console.log(`Current firebase project is ${currentApp.projectId}`);
  } catch (e) {
    console.log(e);
  }
})();
  1. 先ほどの.firebasercを読み込み
  2. 実行時の引数(process.argv[2])からプロジェクトを特定。
  3. useコマンドで使用するプロジェクトを宣言
  4. プロジェクト内のWebアプリ一覧を取得
  5. とりあえず0番目のアプリを現在のアプリだとする。Webアプリが複数ある場合はここでさらに特定が必要です。
  6. 設定ファイルの内容を取得
  7. 設定ファイルをwrite

このような流れで、js/firebaseConfig.jsが生成されます。
後々整形するかもと思ったのでfsモジュールを使ってwriteしていますが、このように

await firebaseTools.apps.sdkconfig(
  'WEB',
  currentApp.appId,
  { out: './js/firebaseConfig.js' }
);

3番目の引数にファイルの作成先を直接指定しても書き込んでくれます。

.firebasercで設定したプロジェクトエイリアスを引数にして、コマンドを叩いてみてください。

$ node scripts/setFirebaseConfig.js default

生成される設定ファイルは、

js/firebaseConfig.js
// Copy and paste this into your JavaScript code to initialize the Firebase SDK.
// You will also need to load the Firebase SDK.
// See https://firebase.google.com/docs/web/setup for more details.

firebase.initializeApp({
  "projectId": "project-id",
  "appId": "1:000000000000:web:xxxxxxxxxxxxxxxxxx",
  "databaseURL": "https://project-id.firebaseio.com",
  "storageBucket": "project-id.appspot.com",
  "locationId": "location-id",
  "apiKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "authDomain": "project-id.firebaseapp.com",
  "messagingSenderId": "0000000000000000",
  "measurementId": "G-XXXXXXXXXXX"
});

このようなフォーマットになっています。
これをそのままExpoなどで使うには,

global.js
import firebase from 'firebase';
import "firebase/firestore";
import "firebase/functions";

global.firebase = firebase;

このようにあらかじめグローバル変数にfirebaseをセットしておけばOKです。

あとは
.gitignorejs/firebaseConfig.jsを追加して、

package.json
  "scripts": {
    "fb:config": "node scripts/setFirebaseConfig.js",
    "start": "npm run fb:config default && expo start",
    "android": "npm run fb:config default && expo start --android",
    "ios": "npm run fb:config default && expo start --ios",
    "web": "npm run fb:config default && expo start --web",
    "eject": "expo eject",
    "test": "npm run fb:config test && jest --coverage"
  },

package.jsonで適宜スクリプトを実行するよう定義しておきます。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4