Firebaseエミュレーターとは何か?完全無料・無課金で使い倒せる最強ツール(データ保存方法やnpm run devとの違い|firebase emulators:start –import=./saved-data –export-on-exit)

firebase-prograshi(プロぐらし)-kv Firebase
記事内に広告が含まれていることがあります。

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エミュレーターのサービス毎の各ポートは決められています。

サービスポート番号接続関数
Firestore8080connectFirestoreEmulator
Auth9099connectAuthEmulator
Functions5001connectFunctionsEmulator
Storage9199connectStorageEmulator
Realtime DB9000connectDatabaseEmulator
ポート番号の変更も可能

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データベース, ログイン機能, サーバー処理
目的コードの変更を画面に即座に反映させるデータの保存や取得の仕組みをローカルで試す
Point

Firebaseエミュレーターを使う場合は基本的に、1つのターミナルでnpm run devを実行し、別のターミナルでfirebase emulators:startをします。

タイトルとURLをコピーしました