指令以 Firebase CLI 文件 與 Emulator Suite 文件 為準、最後檢查日 2026-06-16。

Firestore local emulator quickstart 的核心責任是建立後續 Security Rules 測試與 distributed counter lab 共用的本地環境。這個 lab 把 Firestore 從抽象服務轉成可觀察的 emulator、規則檔、seed 資料與 query 結果,全程不碰雲端專案。

範圍從 lab 環境與前置開始,依序是 emulator 設定、baseline 規則、啟動 emulator、用 admin SDK seed 資料、query baseline,到 cleanup 為止。

Lab 環境與前置

Lab 在本地資料夾跑,需要 Node.js 與 Firebase CLI。以下命令建立一個可刪除的工作區並裝好工具。

1mkdir -p /tmp/firestore-lab
2cd /tmp/firestore-lab
3
4# Firebase CLI(已裝可跳過);用 npx 也可避免全域安裝
5npm install -g firebase-tools
6
7# 本 lab 的 Node 依賴
8npm init -y
9npm install firebase-admin

emulator 需要 Java runtime(Firestore emulator 跑在 JVM 上),而且版本有下限:firebase-tools 15.32.0 遇到 Java 17 時直接報錯、拒絕啟動 emulator,錯誤訊息寫明要 JDK 21 以上。java -version 看的是版本號,不只是有沒有裝;版本不到的話先裝新版 JDK 再繼續。驗收 artifact 是 /tmp/firestore-lab 工作區。

Emulator 設定

firebase.json 的核心責任是宣告要啟動哪些 emulator 與對應 port。這裡只開 Firestore 與 UI,不需要真實 Firebase 專案——emulator 用一個 demo project id 即可,demo- 前綴讓 CLI 知道這是純本地、不連雲端。

 1cat > firebase.json <<'JSON'
 2{
 3  "emulators": {
 4    "firestore": { "port": 8080 },
 5    "ui": { "enabled": true, "port": 4000 }
 6  },
 7  "firestore": {
 8    "rules": "firestore.rules"
 9  }
10}
11JSON

Baseline 規則

firestore.rules 的核心責任是定義授權。Quickstart 先用一組明確的 owner-scoped 規則(不是 allow read, write: if true,那是 Security Rules 授權建模 記錄的失敗案例「allow read, write: if true 上線沒收」)。這份規則後續在 Security Rules test lab 會被測試覆蓋。

 1cat > firestore.rules <<'RULES'
 2rules_version = '2';
 3service cloud.firestore {
 4  match /databases/{database}/documents {
 5    match /notes/{noteId} {
 6      allow read: if request.auth != null
 7                  && resource.data.ownerId == request.auth.uid;
 8      allow create: if request.auth != null
 9                    && request.resource.data.ownerId == request.auth.uid;
10      allow update, delete: if request.auth != null
11                            && resource.data.ownerId == request.auth.uid;
12    }
13  }
14}
15RULES

啟動 emulator

啟動 emulator 的核心責任是讓本地有一個可寫可查的 Firestore。用 demo project id 啟動,emulator UI 在 http://localhost:4000 可看到資料。

1firebase emulators:start --only firestore --project demo-firestore-lab

這個指令會 foreground 跑住 emulator。保持它開著,另開一個 terminal 做 seed 與 query。終端輸出會印出 Firestore emulator 的位址(預設 localhost:8080)與 UI 位址。

Seed 資料(admin SDK 繞過規則)

Seed 的核心責任是建立可重跑的測試資料。admin SDK 連到 emulator 時繞過 Security Rules(模擬後端的特權寫入),適合種資料。關鍵是設 FIRESTORE_EMULATOR_HOST 環境變數——有了它,admin SDK 的寫入全部導向 emulator、不需要任何雲端 credential。

 1cat > seed.js <<'JS'
 2const { initializeApp } = require('firebase-admin/app');
 3const { getFirestore } = require('firebase-admin/firestore');
 4initializeApp({ projectId: 'demo-firestore-lab' });
 5const db = getFirestore();
 6
 7async function main() {
 8  await db.collection('notes').doc('n1').set({
 9    ownerId: 'alice', text: 'Alice first note', createdAt: Date.now(),
10  });
11  await db.collection('notes').doc('n2').set({
12    ownerId: 'bob', text: 'Bob first note', createdAt: Date.now(),
13  });
14  console.log('seeded 2 notes');
15}
16main().then(() => process.exit(0));
17JS
18
19# 在新 terminal、同 lab 目錄下
20export FIRESTORE_EMULATOR_HOST=localhost:8080
21node seed.js

預期輸出 seeded 2 notes。打開 http://localhost:4000/firestore 應看到 notes collection 下兩筆 document。

Query baseline

Query 的核心責任是確認資料可讀、access pattern 入口可用。admin SDK 同樣繞過規則,這裡驗證的是資料與查詢本身(規則的放行 / 拒絕在 Security Rules test lab 用 client context 驗)。

 1cat > query.js <<'JS'
 2const { initializeApp } = require('firebase-admin/app');
 3const { getFirestore } = require('firebase-admin/firestore');
 4initializeApp({ projectId: 'demo-firestore-lab' });
 5const db = getFirestore();
 6
 7async function main() {
 8  const snap = await db.collection('notes')
 9    .where('ownerId', '==', 'alice').get();
10  console.log(`alice notes: ${snap.size}`);
11  snap.forEach((d) => console.log(d.id, d.data().text));
12}
13main().then(() => process.exit(0));
14JS
15
16export FIRESTORE_EMULATOR_HOST=localhost:8080
17node query.js

預期輸出 alice notes: 1 與 n1 Alice first note。這證明 where('ownerId', '==', ...) 的 access pattern 成立——它也正是 client 端要自帶、好讓 owner-scoped 規則放行的查詢條件。

Artifact 與驗收

Artifact路徑 / 來源驗收
emulator configfirebase.jsonFirestore + UI port 宣告
規則檔firestore.rulesowner-scoped、非 if true
seed 結果seed.js output + UInotes/n1、notes/n2 存在
query 結果query.js outputalice notes: 1

Cleanup

Cleanup 的核心責任是讓 lab 可重跑。emulator 的資料在 process 結束時預設不持久化(除非設了 --export-on-exit),所以停掉 emulator 等於清空資料。

1# 停掉 emulator:在 emulator terminal 按 Ctrl-C
2# 移除整個工作區
3rm -rf /tmp/firestore-lab

若想保留 emulator 資料跨 session,啟動時加 --import=./data --export-on-exit=./data;lab 預設不持久化,保持每次乾淨起步。

完成本篇後,下一步進 Security Rules test lab(把上面的規則寫成自動化測試)或 Distributed counter lab。

引用路徑