Firebaseを導入したものの、「無料枠を超えて課金されないか不安」「本番データを汚さずにテストしたい」と悩んでいませんか?
そんな開発者の救世主となるのがFirebaseエミュレーターです。
これは自分のPC内に「仮想のFirebase環境」を構築するツールで、データの読み書きやCloud Functionsの実行が完全無料・無制限で行えます。
本記事では、初心者が混乱しやすい「npm run dev」との役割の違いから、開発効率を上げるデータの保存・復元方法(--import / --export-on-exit)を解説しています。
この記事を読めば、高価なクラウド資源を1円も消費せず、安全かつ高速に開発を進める「最強のローカル環境」が構築できるようになります。
Firebaseエミュレーターとは何か?
Firebaseエミュレーターとは、自分のPCの中に作る、仮想Firebaseです。
通常、FirestoreやAuthentication、FunctionsなどのFirebaseのサービスを使うには、インターネット上のGoogleのサーバーに接続する必要があります。
しかし、エミュレーターを使うと、ネットに繋がなくても自分のPC内でFirebaseの機能を再現できます。
エミュレーターとは、ある特定のハードウェアやOSの動作環境を、別のコンピューター上でソフトウェア的に「そっくりそのまま」模倣・再現する仕組みのことです。
語源の「emulate」は「模倣する」という意味です。
完全無料・無課金
エミュレーターを使う最大のメリットは、完全無料・無課金だということです。
通常は従量課金
Firebaseのサービスは従量課金になっています。Cloud functionsを使う場合は有料のBlazeプランにしなければいけない(無料枠があるがクレジットカードの登録が必要)といった条件があります。
コードにバグがあり無限ループによって知らないうちに大量の課金が発生するリスクもあります。
- 呼び出し回数
- 実行時間
- アウトバウンド通信(外部への通信)
エミュレーターは枠を一切消費しない
エミュレーターは自分のPCのメモリとCPUを使って動くので、Googleのサーバーと通信せず、自分のPC内で完結します。
このため、エミュレーターを使えば何万回実行しても0円です。
エミュレーターの容量とメモリの使用
インストール時の容量は約 100MB〜300MB
Firebaseエミュレーターを使うことでPCの容量を圧迫することはほとんどありません。インストール時の容量は約 100MB〜300MBです。
firebase-tools というパッケージの一部としてインストールされま、実行には Java (JRE) が必要ですが、これらを合わせても数百MB程度です。スマホの写真数枚〜数十枚分くらいの感覚です。
CPUとメモリへの負荷
Firebaseエミュレーターはクラウド上の本物のFirebaseには接続せず、自分のPC内の仮想Firebaseを使います。
そのためメモリを消費します。メモリの消費量はそこまで多くはないので、16GB以上あれば特に問題が発生することはありません。
データの保存にはオプションの指定が必要
デフォルトではデータを保存しない
Firebaseエミュレーターは本物のFirebaseと接続しません。
このため、Authのログイン情報やFirestoreに保存したデータはローカル環境のメモリに一時保存されています。
Firebaseエミュレーターがオフになった時点でそれらのデータは消えてしまいます。
エミュレーターを起動・終了する際のコマンドに特定のオプションを付け足せば、データを保存できるようになります。
データ保存方法①【起動&終了時】自動インポートとエクスポート
エミュレータは通常だとオフになったときにデータが消えてしまいますが、エクスポートとインポートすることで、データを永続的に保存することも可能です。
実行方法はとても簡単で、エミュレーターを起動・終了する際のコマンドに特定のオプションを付け足すだけです。
firebase emulators:start --import=./saved-data --export-on-exit指定したフォルダで保持するのは常に最新のデータのみです。中間地点のバックアップを残したい場合は、「firebase emulators:export ./違うディレクトリパス」を実行する必要があります。
–import=./saved-data
「./saved-data」というフォルダからデータを読み込んで起動する、という指示です。
–export-on-exit
エミュレーターを Ctrl + C で終了する瞬間に、その時のデータを「./saved-data」フォルダに書き出す、という指示です。
データ保存方法② 開発途中の保存
上記コマンドだとデータを保存するのはctrl + cでexitしたときのみです。
「開発途中で現在のデータを念のため保存しておきたい!」と言う場合は、別のターミナルを開いて以下のコードを実行します。
firebase emulators:export ./saved-dataもしデフォルトのフォルダ以外の場所に保存したい場合は以下のように保存先を変更します。(例:./backup-data に保存する場合)
firebase emulators:export ./backup-dataエミュレータの起動と停止
Firebaseエミュレータの起動と停止は簡単です。
エミュレータの起動
エミュレーターを起動するには、以下のコマンドを実行します。
firebase emulators:start
データを保持したい場合は以下のようオプションをつけて起動します。
firebase emulators:start --import=./saved-data --export-on-exitエミュレーターの停止
エミュレーターを停止するには、「ctrl + c」をするだけです。
これでPCのメモリも開放されます。
開発中と本番での自動切換え
firebase.tsに条件を追記する
自分のPCで開発中はエミュレーターを使い、公開した後は本物のFirebaseを使うという切り替えも、簡単に自動化できます。
Firebaseを自動化しているファイル(firebase.js / firebase.ts)で initializeAppを行っているファイルに①エミュレーターのインポートと②条件分岐を追記します。
import { initializeApp } from "firebase/app";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore"; //connectFirestoreEmulatorを追加
import { getAuth, connectAuthEmulator } from "firebase/auth"; //connectAuthEmulatorを追加
import { getFunctions, connectFunctionsEmulator } from "firebase/functions"; //connectFunctionsEmulatorを追加
import { getStorage, connectStorageEmulator } from "firebase/storage"; //connectStorageEmulatorを追加// localhostの場合、すべての接続先をエミュレーターに切り替える
if (typeof window !== "undefined" && window.location.hostname === "localhost") {
connectFirestoreEmulator(db, "localhost", 8080); //Firestore
connectAuthEmulator(auth, "http://localhost:9099"); //Authentication
connectFunctionsEmulator(functions, "localhost", 5001); //Cloud function
connectStorageEmulator(storage, "localhost", 9199); //Firestorage
console.log("Firebase services connected to Emulator");
}※使わないサービスはコメントアウトか削除してください。
ファイルの全体像としては以下のようになります。
import { initializeApp } from "firebase/app";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { getAuth, connectAuthEmulator } from "firebase/auth";
import { getFunctions, connectFunctionsEmulator } from "firebase/functions";
import { getStorage, connectStorageEmulator } from "firebase/storage";
const firebaseConfig = { /* あなたの設定 */ };
const app = initializeApp(firebaseConfig);
// 各サービスのインスタンスを作成
const db = getFirestore(app);
const auth = getAuth(app);
const functions = getFunctions(app);
const storage = getStorage(app);
// localhostの場合、すべての接続先をエミュレーターに切り替える
if (typeof window !== "undefined" && window.location.hostname === "localhost") {
connectFirestoreEmulator(db, "localhost", 8080);
connectAuthEmulator(auth, "http://localhost:9099");
connectFunctionsEmulator(functions, "localhost", 5001);
connectStorageEmulator(storage, "localhost", 9199);
console.log("Firebase services connected to Emulator");
}
export { db, auth, functions, storage };(補足)if文の書き方の注意点
エミュレーターの接続条件を記述する際のif文の書き方がいくつかあります。
.env.localでどのFirebaseに接続するか切り替える
if (process.env.NEXT_PUBLIC_USE_FIREBASE_EMULATOR === 'true' && process.env.NODE_ENV === 'development') {・・・}.env.localの環境変数「NEXT_PUBLIC_USE_FIREBASE_EMULATOR」の値を見に行きます。
「開発環境だけどクラウド上のFirebaseに接続してテストしたい」と言う場合に、.env.localの環境変数をfalseにするだけで対応できます。
npm run devで常にエミュレーターにつながってしまう
if (process.env.NODE_ENV === 'development') {・・・}この場合、npm run devを実行したときに、必ずエミュレーターにつながってしまいます。
開発環境でクラウド上のFirebaseをテストしたいときに不便です。
(NG)サーバー側のコード実行でエラーが出る
if (location.hostname === "localhost") {・・・}上記の場合、ブラウザで動くときは問題ありませんが、サーバー側(SSR)でコードが実行された瞬間に「locationという変数がない」というエラーが出てアプリが止まってしまうことがあります。
(非推奨)サーバー側の処理がFirebaseエミュレーターにつながらない
if (typeof window !== "undefined" && window.location.hostname === "localhost") {・・・}typeof window !== “undefined” を追加することで、ブラウザ環境以外、すなわちサーバーでの処理はエミュレーターを使わない設定になります。
ただし、Admin SDKなどサーバー側で使うFirebaseのサービスを使う場合にエミュレーターに接続されなくなります。
ポートは決められている
Firebaseエミュレーターのサービス毎の各ポートは決められています。
| サービス | ポート番号 | 接続関数 |
| Firestore | 8080 | connectFirestoreEmulator |
| Auth | 9099 | connectAuthEmulator |
| Functions | 5001 | connectFunctionsEmulator |
| Storage | 9199 | connectStorageEmulator |
| Realtime DB | 9000 | connectDatabaseEmulator |
Firebase CLIの設定ファイル「firebase.json」でポート番号を変更することも可能です。Dockerなどで指定したポートが既に使われている場合は変更する必要があります。
{
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8081 //デフォルトの8080から8081に変更
},
"functions": {
"port": 5001
},
"ui": {
"enabled": true,
"port": 4000 // 管理画面自体のポートも変えられます
}
}
}※firebase.jsonでサービスのポート番号を変更した場合は、firebase.tsのポート番号も変更する必要があります。
// firebase.json で 8081 に変えた場合
connectFirestoreEmulator(db, "localhost", 8081);npm run devとの違い
npm run devもターミナルでアプリを起動するコマンドです。同じくターミナルで実行するfirebase emulators:startとは起動する対象が違います。
npm run devはフロントエンドのアプリケーションを起動し、firebase emulators:startはバックエンドのアプリケーションを起動します。
| 項目 | npm run dev (ViteやNext.jsなど) | Firebaseエミュレーター |
| 対象 | フロントエンド(画面) | バックエンド(機能・データ) |
| 動くもの | React, Vue, Next.jsなどのUI | データベース, ログイン機能, サーバー処理 |
| 目的 | コードの変更を画面に即座に反映させる | データの保存や取得の仕組みをローカルで試す |
Firebaseエミュレーターを使う場合は基本的に、1つのターミナルでnpm run devを実行し、別のターミナルでfirebase emulators:startをします。


