Firebase Local Emulator Suite を使ってみた
Firebaseを使ったアプリの開発中、アプリのバグによってFirestoreへの読み取りリクエストが大量に発生し、一瞬で無料利用枠の上限に達してしまったことがあリました。
そこで、開発中にFirestoreをローカルでモックできる手段は無いか探していたところ、Firebase Local Emulator Suite
というものを見つけたので試してみました。
インストール
以下コマンドでインストールします。
sudo npm install -g firebase-tools
また、エミュレータの実行にはJava(バージョン11以降)が必要でした。事前にインストールして、java
コマンドのPATHを通しておく必要があります。
筆者は以下リンクよりJava18をインストールしました。
初期設定
初期設定をします。
firebase init
最初の選択肢で、Emulators: Set up local emulators for Firebase products
を選択しました。他にも利用するサービスとして、Hosting
、Storage
、Firestore
を選択しました。
Emulators Setup
では、利用するエミュレータとして、Authentication Emulator
、Firestore Emulator
、Hosting Emulator
、Storage Emulator
を選択しました。
各エミュレータが利用するポートはデフォルトのまま、Would you like to enable the Emulator UI?
の質問についてはこの時点ではよく分からなかったので、Y
としておきました。
その他の設定は基本デフォルトでよしなに設定しました。
エミュレータの開始
以下のコマンドで開始します。
firebase emulators:start
-
2022/9/1追記
データをエクスポートできるようにするため、以下のコマンドの方が良いです。firebase emulators:start --import=./firebase_export --export-on-exit
すると、以下のように出力されました。
i emulators: Starting emulators: auth, firestore, hosting, storage
i firestore: Firestore Emulator logging to firestore-debug.log
i emulators: Shutting down emulators.
i firestore: Stopping Firestore Emulator
i auth: Stopping Authentication Emulator
i storage: Stopping Storage Emulator
i hub: Stopping emulator hub
⚠ hosting: Port 5000 is not open on localhost, could not start Hosting Emulator.
⚠ hosting: To select a different host/port, specify that host/port in a firebase.json config file:
{
// ...
"emulators": {
"hosting": {
"host": "HOST",
"port": "PORT"
}
}
}
i emulators: Shutting down emulators.
Error: Could not start Hosting Emulator, port taken.
5000番ポートが使えないとのことだったので、firebase.json
を編集します。
{
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8080
},
"hosting": {
- "port": 5000
+ "port": 15000
},
"storage": {
"port": 9199
},
"ui": {
"enabled": true
}
再度、開始すると上手く行きました。
i emulators: Starting emulators: auth, firestore, hosting, storage
i firestore: Firestore Emulator logging to firestore-debug.log
i hosting: Serving hosting files from: public
✔ hosting: Local server: http://localhost:15000
i ui: downloading ui-v1.9.0.zip...
Progress: =====================================================================================================================================> (100% of 4MB)
i ui: Emulator UI logging to ui-debug.log
┌─────────────────────────────────────────────────────────────┐
│ ✔ All emulators ready! It is now safe to connect your app. │
│ i View Emulator UI at http://localhost:4000 │
└─────────────────────────────────────────────────────────────┘
┌────────────────┬─────────────────┬─────────────────────────────────┐
│ Emulator │ Host:Port │ View in Emulator UI │
├────────────────┼─────────────────┼─────────────────────────────────┤
│ Authentication │ localhost:9099 │ http://localhost:4000/auth │
├────────────────┼─────────────────┼─────────────────────────────────┤
│ Firestore │ localhost:8080 │ http://localhost:4000/firestore │
├────────────────┼─────────────────┼─────────────────────────────────┤
│ Hosting │ localhost:15000 │ n/a │
├────────────────┼─────────────────┼─────────────────────────────────┤
│ Storage │ localhost:9199 │ http://localhost:4000/storage │
└────────────────┴─────────────────┴─────────────────────────────────┘
Emulator Hub running at localhost:4400
Other reserved ports: 4500
Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
試しに、FirestoreのEmulator UI(http://localhost:4000/firestore)
にアクセスしてみると、以下のような画面が開きました。
こちらの画面で、実際のFirestoreのUIと同じようにテストデータの作成を行うことができます。
エミュレータの利用方法
コード内でエミュレータを利用するには、以下のように書きます。
ポイントは、最後にconnect~~Emulator
を呼び出すことです。
import { initializeApp } from "firebase/app";
import { connectAuthEmulator, getAuth } from "firebase/auth";
import { connectFirestoreEmulator, getFirestore } from "firebase/firestore";
const firebaseConfig = {
<キー情報のため省略>
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth(app);
connectFirestoreEmulator(db, "localhost", 8080);
connectAuthEmulator(auth, "http://localhost:9099");
利用するエミュレータによって、引数の指定方法が若干異なっています。
これで、コード内でFirebaseのAPIを実行する際に、ローカルで起動したエミュレータを使ってくれるようになりました。
(2022/9/1追記)データのインポート・エクスポート
エミュレータを停止すると、エミュレータ上で作成されたデータは破棄されます。
そのため、一度作成したデータを保存しておくには、データのエクスポートが必要です。
以下のコマンドでデータをエクスポートできます。
firebase emulators:export ./firebase_export/
と思って実行したのですが、以下のようなエラーが発生しました。
Error: Did not find any running emulators for project
こちらのissueにあった対処方法を参考にします。
-
一度、動作しているエミュレータを停止します。(このタイミングで保存されているデータは消えますが、一旦止むなし)
-
firestore-debug.log
が作成されていると思うので、削除します。 -
以下のコマンドでエミュレータを再起動します。
firebase emulators:start --import=./firebase_export --export-on-exit
-
別ターミナルで再度エクスポートのコマンドを実行してみます。
firebase emulators:export ./firebase_export/
エクスポートに成功しました。
次回起動時に、データをインポートして起動するには、同様に以下のコマンドで起動します。
firebase emulators:start --import=./firebase_export --export-on-exit
ちなみに、--export-on-exit
オプションを指定することで、エミュレータの停止時に自動的にデータがエクスポートされるようになります。エクスポート先は--import
に指定したディレクトリです。
(2022/10/17追記)エミュレータ停止時の不具合
Ctrl+C
でエミュレータを停止すると、たまにエミュレータが正常に停止せず、次回起動時に以下のようなエラーメッセージが表示されることがありました。
Error: Could not start Firestore Emulator, port taken.
一次対処的ではありますが、以下コマンドで直接プロセスを落とすことで、再度エミュレータを起動できるようになります。
※ポート番号は、firebase.json
に記述したものを指定します。
lsof -t -i:8080 -i:15000 -i:9099 -i:9199 | xargs kill -9
まとめ
Firebase Local Emulator Suite
を使ってみました。
アプリの開発中に、Firebase APIのリクエスト上限に達したり、下手に課金されたり、といったことを回避するためのツールとして重宝したいです。
Discussion