---
# System prepended metadata

title: Firebase 無主機開發 2026 完全指南：從 Cloud Functions 到 App Hosting，少寫一行伺服器配置的工程美學

---

---
title: Firebase 無主機開發 2026 完全指南：從 Cloud Functions 到 App Hosting，少寫一行伺服器配置的工程美學
description: 工程主管必讀的 Firebase 架構評估指南。涵蓋 Cloud Functions 2nd Gen、Firestore Security Rules、App Hosting、分片計數器、真實成本計算與 Supabase 對戰。
keywords: Firebase, 無主機開發, Serverless, Cloud Functions, Firestore, App Hosting, Supabase, 後端即服務
date: 2026-05-05
---

# Firebase 無主機開發 2026 完全指南：從 Cloud Functions 到 App Hosting，少寫一行伺服器配置的工程美學

我前陣子聽到一個案例：某家 SaaS 公司用 Firebase 開發 MVP，產品起飛後幾個月，使用者來到 1,000 萬，月帳單從 $1,200 飆到 $30,000，而且**沒有任何告警**，直接收到一張五位數帳單。最後他們花了三個月把後端整個改寫到 Supabase，月帳單回到 $25 ([Horizon Dev 2026 比較報告](https://horizon.dev/blog/supabase-vs-firebase-startups/) )。

這個故事我不是要嚇你「Firebase 不能用」，而是想說：**無主機（Serverless）這條路，不是只有 `firebase deploy` 就萬事 OK。**

Firebase 在 2026 年仍然是 BaaS 領域最完整的方案之一——根據 [Tech Insider 2026 對比報告](https://tech-insider.org/supabase-vs-firebase-2026-2/) 與 [Horizon Dev 比較](https://horizon.dev/blog/supabase-vs-firebase-startups/) ，weekly npm downloads 約 320 萬，遙遙領先 Supabase 的 45 萬。但它的計費模式、Vendor Lock-in 風險、Firestore 與 SQL 思維的差異，每一項都可能讓沒做好功課的團隊吃苦頭。

這篇文章把官方文件、生產環境踩坑、2026 年最新定價、AI 整合（Genkit、Vertex AI）、和 Supabase 的最新對比通通整理在一起，讓你看完後能做出明確的架構決策——不只是「跟風用」，而是**用得對、用得久、用得不爆預算**。

**本文前置知識**：你需要對 Node.js / TypeScript、基礎雲端概念（容器、CDN、CI/CD）有一定理解。文中所有規格與定價以 2026 年 5 月官方文件為準。

---

## 一、什麼是 Firebase 無主機？拆解五層核心服務

![firebase-無主機-五層架構](https://hackmd.io/_uploads/HkFiuZDAZe.jpg)

「Serverless」字面意思是「沒有伺服器」，但這顯然不對——程式碼總得跑在某個地方。它的真正意涵是：**伺服器的存在對你透明**，你不用 SSH、不用 patch OS、不用設 nginx，雲端會在請求進來的瞬間動態分配資源，閒置時就回收。

Firebase 的無主機體系由五個核心組件構成：

| 組件 | 角色 | 主要負責 |
| --- | --- | --- |
| **Cloud Functions for Firebase** | 運算層 | 執行後端邏輯、響應事件或 HTTPS 請求 |
| **Cloud Firestore / Realtime Database** | 資料層 | NoSQL 儲存與多端即時同步 |
| **Firebase Authentication** | 安全層 | 註冊登入、社群登入、多因素驗證 |
| **Firebase Hosting / App Hosting** | 部署層 | 靜態託管、SSR 應用、CDN 分發 |
| **Cloud Storage for Firebase** | 儲存層 | 圖片、影片等大型檔案 |

從架構視角看，這五層的關係是這樣的：

```mermaid
flowchart LR
    Client[Web / Mobile Client] -->|HTTPS| Hosting[Firebase Hosting / App Hosting]
    Client -->|SDK| Auth[Firebase Authentication]
    Client -->|SDK + Rules| FS[Cloud Firestore]
    Client -->|SDK| Storage[Cloud Storage]
    Hosting --> CF[Cloud Functions]
    Auth -.事件.-> CF
    FS -.事件.-> CF
    Storage -.事件.-> CF
    CF --> FS
    CF --> Storage
```

最關鍵的設計選擇在於：**客戶端 SDK 直接打資料庫**，不需要中間人（傳統的後端 API 伺服器）。這帶來兩個極端：
- **好處**：開發者不用為每個 CRUD 寫 REST endpoint，前端工程師也能完成原本要兩個團隊才做得完的事
- **壞處**：所有的權限驗證、資料 schema 防護，全靠 Security Rules 來把關。寫不好就是巨大的安全洞

每一層都有自己的 know-how。我們從跑邏輯的 Cloud Functions 開始拆。

---

## 二、Cloud Functions 1st vs 2nd Gen：終於不用為冷啟動煩惱了

![firebase-cloud-functions-1代vs2代](https://hackmd.io/_uploads/Skg2O-PRWg.jpg)

Cloud Functions for Firebase 在 2022 年底推出第二代（2nd Gen），但很多 2020 年前的 Firebase 專案到今天還在跑 1st Gen——這幾乎可以說是「在用古董機種」。兩代差異不只是版本號，根本是不同層級的東西。

### 規格對比

引用自 [官方 Firebase 版本對比文件](https://firebase.google.com/docs/functions/version-comparison) 與 [oneuptime 2026 v2 評測](https://oneuptime.com/blog/post/2026-02-17-how-to-use-firebase-cloud-functions-v2-with-cloud-run-under-the-hood/view) ：

| 規格 | 1st Gen | 2nd Gen |
| --- | --- | --- |
| HTTP timeout | 9 分鐘（540s） | **60 分鐘（3600s）** |
| 事件觸發 timeout | 9 分鐘 | 9 分鐘 |
| 最大記憶體 | 8 GB | **16 GiB（GA）** |
| 最多 vCPU | 2 | **4（GA）** |
| Concurrency | **1 req/instance** | **預設 80，可設 1–1000** |
| 底層基礎 | Cloud Functions 原生 | **Cloud Run + Eventarc** |
| Min instances | 支援 | 原生支援 |
| Traffic splitting | 不支援 | 支援 |

最關鍵的差異是 **concurrency**。在 1st Gen 中，每個實例只能處理一個請求——意思是當 50 個請求同時湧入，系統就得啟動 50 個新實例，每個都要付出冷啟動代價（約 100ms 到數秒）。

但在 2nd Gen 中，[一個實例可以同時處理最多 1000 個請求](https://firebase.blog/posts/2022/12/cloud-functions-firebase-v2/) 。這意味著突發 50 個請求**完全不會觸發冷啟動**——一個實例就吃下了。

### 程式碼遷移範例

從 1st Gen 改寫到 2nd Gen，import 路徑是關鍵：

```javascript
// 1st Gen — 舊版
const functions = require("firebase-functions/v1");

exports.helloWorld = functions.https.onRequest((req, res) => {
  res.send("Hello from 1st Gen");
});
```

```javascript
// 2nd Gen — 新版，加上 concurrency 設定
const { onRequest } = require("firebase-functions/v2/https");

exports.helloWorld = onRequest({
  concurrency: 500,         // 單一實例最多並行 500 請求
  minInstances: 1,          // 保持 1 個實例預熱，徹底消滅冷啟動
  cpu: 1,
  memory: "512MiB",
  timeoutSeconds: 60,
}, (req, res) => {
  res.send("Hello from 2nd Gen");
});
```

### 冷啟動三招實戰

冷啟動是無主機的「原罪」，但 2nd Gen 加上幾個技巧後幾乎可以忽略：

**1. 設置 minInstances**
對延遲敏感的函數（用戶登入、結帳），保留 1–2 個實例預熱。會多付一點錢，但首次請求延遲從 2 秒降到 50ms。

**2. 延遲載入大型依賴**
分析 Java Code Geeks 的 [冷啟動深度報告](https://www.javacodegeeks.com/2025/04/comprehensive-analysis-of-firebase-functions-cold-starts.html) 指出，JavaScript 函數的啟動時間幾乎全花在 `require()`/`import`：

```javascript
// ❌ 全域載入：每次冷啟動都吃 800ms
const { BigQuery } = require("@google-cloud/bigquery");

exports.report = onRequest((req, res) => {
  const bq = new BigQuery();
  // ...
});

// ✅ 路徑內載入：只有實際用到時才載入
exports.report = onRequest((req, res) => {
  if (req.path === "/heavy-report") {
    const { BigQuery } = require("@google-cloud/bigquery");
    const bq = new BigQuery();
    // ...
  }
});
```

**3. 用 onInit() 推遲全域初始化**
全域變數的初始化會在每次冷啟動時執行。把昂貴的初始化（連線池、SDK 客戶端）放進 `onInit()` hook，避免部署時 timeout。

> **Tip**：1st Gen 還在運作，但 [Google 已宣告 2025/02/18 起 1st Gen 強制使用 Artifact Registry](https://community.flutterflow.io/ask-the-community/post/firebase---migrate-your-cloud-run-functions-1st-generation-to-artifact-rnyX3ugOEVkuaNU) 。新專案請直接從 2nd Gen 開始。

---

## 三、Firestore Security Rules：一張規則表救你十條 API

![firebase-security-rules-安全層](https://hackmd.io/_uploads/SkunuWvCZx.jpg)

無主機架構下最大的安全爭議是「客戶端直接打資料庫」。傳統後端有 middleware 把關，Firebase 用什麼擋？答案是 **Security Rules**——一套部署在伺服器端、客戶端**完全無法竄改**的宣告式語言。

### 基本語法範例

```javascript
service cloud.firestore {
  match /databases/{database}/documents {
    
    // 用戶只能讀寫自己的個人資料
    match /users/{userId} {
      allow read, write: if request.auth != null
                         && request.auth.uid == userId;
    }
    
    // 任何登入者都能讀貼文，但只有作者能改/刪
    match /posts/{postId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null
                    && request.resource.data.authorId == request.auth.uid;
      allow update, delete: if request.auth != null
                            && resource.data.authorId == request.auth.uid;
    }
  }
}
```

### 性能限制：那條 10 次 get() 的紅線

這是 Firebase 老手才知道的坑。根據 [官方規則條件文件](https://firebase.google.com/docs/firestore/security/rules-conditions) ，規則中跨文件查詢有嚴格上限：

- **單一文件請求 / 查詢**：最多 **10 次** `get()` 或 `exists()`
- **批次寫入 / 交易**：總計 **20 次**，但每個操作仍受 10 次限制
- 超過任一上限 → **permission denied error**

舉個實際情境：

```javascript
// ❌ 容易踩到 10 次上限的寫法
match /comments/{commentId} {
  allow create: if get(/databases/$(database)/documents/posts/$(request.resource.data.postId)).data.authorId == request.auth.uid
                || get(/databases/$(database)/documents/admins/$(request.auth.uid)).data.role == "moderator"
                || get(/databases/$(database)/documents/teams/$(get(...).data.teamId)).data.members.hasAny([request.auth.uid]);
}
```

這種「rule 裡面跑 SQL」的寫法會立刻觸發上限。**正確解法是把權限資訊放進 [Custom Claims](https://firebase.google.com/docs/auth/admin/custom-claims) **：

```javascript
// ✅ 直接讀 token 裡的 custom claim，零 get() 呼叫
match /comments/{commentId} {
  allow create: if request.auth.token.role in ["author", "moderator"];
}
```

註冊用戶時透過 Admin SDK 設定 claim：

```typescript
import { getAuth } from "firebase-admin/auth";

await getAuth().setCustomUserClaims(uid, {
  role: "moderator",
  teamId: "team-42",
});
// 用戶下次 ID token 重新整理後就會帶上這些 claim
```

> **Tip**：每個 `get()`/`exists()` 都會被計算為一次 Firestore read，**會收費**——即使規則最終拒絕了請求。把權限放進 token 不只解決 10 次限制，也省下一筆讀取費用。

### Security Rules 的其他冷知識限制

來自 [code.build 規則完整指南](https://code.build/p/firestore-security-rules-example-guide-eyfhvI) ：

- 函數最多 **7 個參數**
- 最多 **10 個 `let` 變數**
- 函數呼叫深度上限 **20**
- 單次請求最多評估 **1000 個表達式**
- **不支援 loop / recursion**

這些限制乍看很嚴苛，但其實是為了讓規則評估維持在納秒級。如果你發現規則寫不下了，那是訊號——你的資料模型該重新設計了。

---

## 四、突破單一文件 1 寫/秒：分片計數器實戰

![firebase-firestore-分片計數器](https://hackmd.io/_uploads/By1T_ZPAZx.jpg)

Firestore 對單一文件的寫入頻率有個硬性限制：**約每秒 1 次**（受 [官方 best practices 文件](https://firebase.google.com/docs/firestore/best-practices) 證實）。對「按讚數」、「即時觀看人數」、「投票統計」這類場景，1 寫/秒根本不夠用。

解法是**分片計數器（Distributed Counters）**：把一個邏輯計數器拆成 N 個分片，寫入時隨機選一個。

### 完整實作範例

以下程式碼基於 [oneuptime 2026 distributed counters 實作教學](https://oneuptime.com/blog/post/2026-02-17-how-to-implement-distributed-counters-in-firestore-for-high-write-scenarios/view) ：

```javascript
import { 
  doc, setDoc, updateDoc, getDocs, collection,
  increment, writeBatch, getFirestore 
} from "firebase/firestore";

const db = getFirestore();
const NUM_SHARDS = 10;

// 1️⃣ 初始化（只做一次）
async function createCounter(counterPath) {
  const batch = writeBatch(db);
  batch.set(doc(db, counterPath), { numShards: NUM_SHARDS });
  
  for (let i = 0; i < NUM_SHARDS; i++) {
    batch.set(doc(db, `${counterPath}/shards/${i}`), { count: 0 });
  }
  
  return batch.commit();
}

// 2️⃣ 寫入：隨機挑分片（每秒可達 NUM_SHARDS 次寫入）
async function incrementCounter(counterPath, amount = 1) {
  const shardId = Math.floor(Math.random() * NUM_SHARDS);
  const shardRef = doc(db, `${counterPath}/shards/${shardId}`);
  await updateDoc(shardRef, { count: increment(amount) });
}

// 3️⃣ 讀取：聚合所有分片
async function getCounterTotal(counterPath) {
  const shardsSnap = await getDocs(collection(db, `${counterPath}/shards`));
  let total = 0;
  shardsSnap.forEach(snap => { total += snap.data().count; });
  return total;
}

// 使用範例
await createCounter("counters/post-123-likes");
await incrementCounter("counters/post-123-likes");
const likes = await getCounterTotal("counters/post-123-likes");
```

### 寫入吞吐 vs 讀取成本的取捨

```mermaid
flowchart TB
    subgraph Write[寫入路徑]
        W1[Client 1] -->|increment| S0[Shard 0]
        W2[Client 2] -->|increment| S5[Shard 5]
        W3[Client 3] -->|increment| S9[Shard 9]
    end
    
    subgraph Read[讀取路徑]
        R[Client] -->|read all shards| Agg[Aggregate Sum]
        Agg --> Total[Total Count]
    end
    
    S0 -.summed.-> Agg
    S5 -.summed.-> Agg
    S9 -.summed.-> Agg
```

| 分片數 | 最大寫入吞吐 | 單次讀取成本 |
| --- | --- | --- |
| 10 | 10 寫/秒 | 10 reads |
| 100 | 100 寫/秒 | 100 reads |
| 1000 | 1000 寫/秒 | 1000 reads |

明顯地，分片越多寫得越快，但每讀一次總和就要付 N 次 read 的錢。對讀多寫多的場景（社群媒體按讚），可以加一個 **roll-up Cloud Function**，定期把所有分片加總寫到一個單一的「rollup 文件」：

```typescript
import { onSchedule } from "firebase-functions/v2/scheduler";
import { getFirestore } from "firebase-admin/firestore";

// 每分鐘聚合一次
export const rollupCounters = onSchedule("every 1 minutes", async () => {
  const db = getFirestore();
  const counterRef = db.doc("counters/post-123-likes");
  const shards = await counterRef.collection("shards").get();
  
  let total = 0;
  shards.forEach(doc => { total += doc.data().count; });
  
  await counterRef.update({ rollupTotal: total, rollupAt: new Date() });
});
```

前端只讀 `counterRef` 一次（1 read）就拿到接近即時的總數。

---

## 五、App Hosting vs Firebase Hosting：你該用哪個？

![firebase-app-hosting-vs-hosting](https://hackmd.io/_uploads/H1OT_ZD0bl.jpg)

Firebase 在 2024 年中推出了 **App Hosting**，是給現代全端框架（Next.js、Angular、Astro）用的下一代託管方案。它和原本的 Firebase Hosting 差別很大，選錯會踩坑。

### 差異全表

引用 [Firebase 官方部落格 App Hosting vs Hosting](https://firebase.blog/posts/2024/05/app-hosting-vs-hosting/) ：

| 維度 | Firebase Hosting（原版） | Firebase App Hosting（2024+） |
| --- | --- | --- |
| 適用場景 | 靜態網站 / SPA | 全棧 SSR / API routes |
| Framework 感知 | 部分（透過 web frameworks 實驗） | **原生 framework-aware** |
| SSR 後端 | Cloud Functions | **Cloud Run（直接）** |
| 建置流程 | Firebase CLI | **Cloud Native Buildpacks** |
| 動態擴展 | 透過 Functions | 原生 Cloud Run scale-to-zero |
| GitHub 整合 | PR Preview Channels | 原生 Git push 部署 |

### 何時該用哪個？

**用 Firebase Hosting（原版）的情況**：
- 純前端 SPA（React、Vue、Svelte）
- 靜態文件網站（部落格、Marketing site）
- 需要極致 CDN 邊緣快取的場景

**用 App Hosting 的情況**：
- Next.js 13+（App Router、Server Components）
- Angular 17+ SSR
- 需要 API routes / middleware 的應用
- 想要 GitHub push 自動部署的工作流

### Hosting 整合 GitHub 的「Git push 即部署」

執行 `firebase init hosting:github` 後，CLI 會幫你做這幾件事：

1. 在 GCP 建立具部署權限的服務帳號
2. 加密 JSON 金鑰並上傳到 GitHub Secrets
3. 產生 YAML workflow，每個 PR 都會獲得**獨立預覽 URL**
4. PR 合併到 main 後自動上線

對小團隊來說，這幾乎就是免費的 CI/CD pipeline，比起自己刻 GitHub Actions + AWS S3 簡單太多。

---

## 六、真實成本計算：Blaze、Supabase、VPS 三方對戰

![firebase-成本對比-blaze-supabase-vps](https://hackmd.io/_uploads/HyxRd-vRWe.jpg)


成本是工程主管最關心的話題。我把 2026 年三方最新定價整理在一起，讓你看清楚不同規模下的真實差異。

### Firebase Blaze 定價（2026/05）

引用自 [Firebase 官方定價頁](https://firebase.google.com/pricing) 與 [Tekpon 2026 計算彙整](https://tekpon.com/software/firebase/pricing/) ：

**Firestore（資料層）**

| 項目 | Spark 免費 | Blaze 計費 |
| --- | --- | --- |
| Reads | 50K / 天 | $0.06 / 100K |
| Writes | 20K / 天 | $0.18 / 100K |
| Deletes | 20K / 天 | $0.02 / 100K |
| 儲存 | 1 GB | $0.108–$0.026 / GB（階梯） |

**Cloud Functions（運算層）**

| 項目 | Spark 免費 | Blaze 計費 |
| --- | --- | --- |
| Invocations | 2M / 月 | $0.40 / 1M |
| GB-seconds | 400K / 月 | 隨資源量計 |

**Hosting / Storage（部署與儲存層）**

| 項目 | Spark 免費 | Blaze 計費 |
| --- | --- | --- |
| Hosting 頻寬 | 10 GB / 月 | **$0.15 / GB（cached）、$0.20 / GB（uncached）** |
| Storage 流量 | — | $0.15 / GB egress |
| Auth phone SMS | — | $0.01–$0.06 / SMS |

> **2026/02/03 重大變更**：[Firebase Cloud Storage 現在強制需要 Blaze 計畫](https://www.githubactionscost.online/supabase-vs-firebase-cost) ——即使你的用量在免費額度內。新專案如果只想用 Spark 計畫，得避開 Cloud Storage。

### 三種規模情境模擬

**情境 A：MVP（1,000 DAU）**

| 項目 | Firebase | Supabase | VPS（DigitalOcean） |
| --- | --- | --- | --- |
| 月費 | **$0**（Spark 涵蓋） | $0（Free tier） | $5–$20（固定） |
| 維運人力 | $0 | $0 | 工程師 20% 工時 |
| **小計** | **$0** | **$0** | **$5 + 人力** |

**情境 B：成長期（10,000 DAU、50K API/天）**

| 項目 | Firebase | Supabase | VPS |
| --- | --- | --- | --- |
| Firestore / DB | ~$30 | $0 | ~$10（VPS DB） |
| Functions | ~$15 | $0 | $0 |
| Hosting + Storage | ~$10 | $0 | $5 |
| **小計** | **~$55** | **$25**（Pro 固定） | **~$25 + 人力** |

**情境 C：規模化（10M DAU、read-heavy）**

| 項目 | Firebase | Supabase | VPS |
| --- | --- | --- | --- |
| 資料庫 | $500–$1,500 | $200–$400 | 自管成本高 |
| Functions / Edge | $300–$800 | 含於 Pro | 自管 |
| **小計** | **$1,000–$3,000** | **$200–$600**（3–5 倍便宜） | **複雜** |

數據驗證：[Tech Insider 2026 對比](https://tech-insider.org/supabase-vs-firebase-2026-2/) 與 [Horizon Dev 客戶案例](https://horizon.dev/blog/supabase-vs-firebase-startups/) 都指出 read-heavy 場景下 Supabase 比 Firebase 便宜 3–5 倍。

### 流量定價特別警告

如果你的應用是**影音串流**或**大量檔案下載**，Firebase Hosting 的 $0.20/GB egress 是個大坑。對比 [GPU Per Hour 2026 egress 對比](https://gpuperhour.com/reference/data-egress) ：

| 平台 | Egress 單價（per TB） |
| --- | --- |
| Cloudflare R2 | **$0**（!） |
| Supabase | $90 |
| Google Cloud | $120 |
| Vercel | $150 |
| **Firebase** | **$200** |
| Netlify | $550 |

對流媒體類產品，把靜態大檔案放 Cloudflare R2 + Firebase 處理動態邏輯是常見的混合架構。

---

## 七、生產踩坑：四個你絕對會遇到的問題

![firebase-生產踩坑-警示](https://hackmd.io/_uploads/rJdROWPCbg.jpg)

讀完官方文件就能寫出生產級應用的時代結束了。我把這四年看過的真實踩坑案例整理成四類——每一條都是某個團隊用真金白銀換來的教訓。

### 踩坑 1：把 SDK 滲透到業務邏輯（最深的鎖定）

```typescript
// ❌ 業務邏輯直接呼叫 Firebase SDK
async function getUser(userId: string) {
  const snap = await getDoc(doc(db, "users", userId));
  return snap.data();
}
```

```typescript
// ✅ 透過 Repository pattern 抽象
interface UserRepository {
  findById(id: string): Promise<User | null>;
}

class FirestoreUserRepository implements UserRepository {
  async findById(id: string) {
    const snap = await getDoc(doc(db, "users", id));
    return snap.exists() ? (snap.data() as User) : null;
  }
}

// 業務層只依賴介面
async function getUser(userId: string, repo: UserRepository) {
  return repo.findById(userId);
}
```

未來要遷到 Supabase / PostgreSQL 時，你只要新寫一個 `PostgresUserRepository`，業務層完全不動。

### 踩坑 2：把 Firestore 當 SQL 用（N+1 帳單炸彈）

```typescript
// ❌ 渲染一個貼文列表，每篇貼文額外查作者 → N+1 reads
const posts = await getDocs(collection(db, "posts")); // 1 read × 100 = 100 reads
for (const post of posts.docs) {
  const author = await getDoc(doc(db, "users", post.data().authorId)); // 100 reads
}
// 結果：渲染一個列表 = 200 reads，1000 個用戶看一次 = 200,000 reads
```

```typescript
// ✅ 去規範化：把作者基本資訊存進貼文
// 寫入時：
await addDoc(collection(db, "posts"), {
  title: "...",
  content: "...",
  authorId: user.uid,
  authorName: user.displayName,    // 冗餘
  authorAvatar: user.photoURL,     // 冗餘
});

// 讀取時：1 query 就拿到全部
const posts = await getDocs(collection(db, "posts")); // 100 reads only
```

「寧可複製 100 次小資料，也不要查 100 次資料庫」——這是 Firestore 的鐵律。

### 踩坑 3：全域初始化過載 → 部署 timeout

```typescript
// ❌ 模組載入時就執行昂貴邏輯
import { GoogleAuth } from "google-auth-library";
const auth = new GoogleAuth({ /* ... */ });
const token = await auth.getAccessToken(); // 部署時就會跑 → timeout

export const myFunction = onRequest((req, res) => { /* ... */ });
```

```typescript
// ✅ 用 onInit hook 推遲到實例真正啟動時
import { onInit } from "firebase-functions/v2/core";

let auth: GoogleAuth;
onInit(async () => {
  auth = new GoogleAuth({ /* ... */ });
});

export const myFunction = onRequest((req, res) => {
  // 在這裡 auth 已經初始化完成
});
```

### 踩坑 4：Security Rules 跨多文件 get() 觸發 10 次上限

承前面 Section 3 的範例，多層權限檢查很容易爆表。**永遠優先用 Custom Claims**，而不是寫巢狀 `get()`。

> **Q&A 補充**：規則 deploy 後生效要多久？根據 [zeriflow 安全最佳實踐](https://zeriflow.com/en/blog/firebase-security-best-practices) ，rules deployment 是原子操作，**幾秒鐘內生效**。但 client SDK 端可能因為網路快取延遲到 1 分鐘。生產部署時務必先在 Emulator Suite 跑完整測試。

---

## 八、AI 時代的 Firebase：Genkit 與 Vertex AI 整合

![firebase-genkit-ai-整合](https://hackmd.io/_uploads/SJAyt-vRWg.jpg)

2026 年的 Firebase 已經不只是 BaaS——它正快速成為 AI 應用的後端首選。從 [Firebase 在 Cloud Next 2026 的官方公告](https://firebase.blog/posts/2026/04/cloud-next-2026-announcements) 加上社群觀察，三個值得注意的動向：

### Genkit：開源 AI 應用框架

[Genkit](https://github.com/genkit-ai/genkit) 是 Google Firebase 團隊推出的開源 AI 框架，支援 JS / Go / Python，提供統一介面接 Google、OpenAI、Anthropic、Ollama 等模型。

```typescript
import { genkit, z } from "genkit";
import { googleAI } from "@genkit-ai/googleai";

const ai = genkit({
  plugins: [googleAI()],
  model: "googleai/gemini-2.5-flash",
});

export const summarize = ai.defineFlow(
  {
    name: "summarize",
    inputSchema: z.string(),
    outputSchema: z.string(),
  },
  async (text) => {
    const { text: summary } = await ai.generate(`Summarize: ${text}`);
    return summary;
  }
);
```

flows 可以直接部署到 Cloud Functions / Cloud Run，所有 Telemetry 自動匯出到 Firebase Console。

### Firebase AI Logic + Vertex AI

[Firebase AI Logic](https://firebase.google.com/docs/ai-logic/models) 讓你直接從客戶端呼叫 Gemini 系列模型，免去自架 API Gateway。配合 App Check 確保只有你的 App 能呼叫。

最新支援的模型：
- `gemini-2.5-flash`、`gemini-2.5-flash-lite`（生產推薦）
- `imagen-4.0-generate-001`、`imagen-4.0-fast-generate-001`、`imagen-4.0-ultra-generate-001`
- `gemini-live-2.5-flash-native-audio`（即時音訊）

注意 `gemini-2.0-flash` 系列將於 2026/06/01 停用，要遷到 2.5。

### Google AI Studio + Firestore 全棧 = 自然語言寫 App

Cloud Next 2026 最重磅的更新是：[Google AI Studio 現在直接整合 Firestore + Authentication](https://firebase.blog/posts/2026/04/cloud-next-2026-announcements) ，可以用自然語言生成包含後端的全棧應用。底層用 Cloud Run 跑 server code，Security Rules 也能自動草擬。

對小型專案而言，這幾乎是「Vibe Coding」的終極形式。

---

## 九、決策清單：你該選 Firebase 還是 Supabase？

這個選擇沒有單一答案——同一家公司不同產品線可能要選不同方案。我把它拆成三個維度去問：你的產品在哪個階段？技術需求是什麼？規模有多大？

### 產品階段

| 階段 | 建議 | 理由 |
| --- | --- | --- |
| MVP / 概念驗證 | **Firebase** | Auth、即時同步、CDN 開箱即用，可用免費額度撐 1–3 個月 |
| 已有 PMF、開始規模化 | 開始監控成本曲線 | 設定預算告警、檢視單頁 read 數 |
| 大規模生產（>100K DAU） | **重新評估** | 視 read/write 比例、流量類型決定是否遷移 |

### 技術需求

| 需求 | 建議 |
| --- | --- |
| 重度 mobile（iOS/Android/Flutter） | **Firebase**（離線快取、FCM 推播無人能敵） |
| 即時協作（聊天、Google Docs 級即時同步） | **Firebase**（Firestore listeners） |
| 複雜報表、多表 JOIN、聚合查詢 | **Supabase / PostgreSQL** |
| AI Agent 應用 | **Firebase + Genkit** |
| 大檔案下載 / 流媒體 | 混合架構（**Firebase + Cloudflare R2**） |

### 抽象層保險策略

無論最後選誰，**在程式碼中保留抽象層**是必做的。

```typescript
// 把所有資料存取藏在 interface 後面
export interface DataStore {
  users: UserRepository;
  posts: PostRepository;
  // ...
}

// 啟動時注入具體實作
const store: DataStore = useFirebase
  ? new FirebaseDataStore(db)
  : new SupabaseDataStore(supabaseClient);
```

短期多寫一兩百行，長期省下你半年重構時間。

---

## 結語：不是不寫伺服器，是把伺服器寫進雲端基因

「無主機」聽起來像逃避，但它真正的意思是把伺服器的存在問題交給雲端、把心力放回業務邏輯上。

Firebase 在 2026 年做到的事情比 5 年前多太多了——2nd Gen Functions 解決了冷啟動、App Hosting 把 Next.js 部署簡化到極致、Genkit 讓 AI 應用三行 code 就能跑、AI Studio 開始能用自然語言寫全棧。

但你也看到了它的代價：Firestore 不是 SQL、Security Rules 有硬性上限、Egress 流量比同行貴一倍、Vendor Lock-in 風險真實存在。

回到開頭那家月帳單從 $1,200 飆到 $30,000 的 SaaS 公司——他們事後復盤發現，問題不是 Firebase「壞」，而是他們從第一天起就**沒有任何抽象層**，沒設預算告警，把 Firestore 當 PostgreSQL 用，列表頁觸發 N+1 reads。等到使用者破百萬，每多一個用戶就是一張帳單。

如果你正在開新專案，我會說：直接用 Firebase，但是**寫 Repository 介面、設 Budget Alert、用 Custom Claims**這三件事，請在第一週就做完。它們加起來不過半天工，能幫你避開 90% 的後悔。

無主機從來不是「免費的午餐」。它是一份你必須懂得怎麼吃的合約——讀懂它，你就能用一半的時間做出原本兩倍規模才做得出的產品。

---

## 延伸閱讀

- [Firebase 官方文件 — Cloud Functions Version Comparison](https://firebase.google.com/docs/functions/version-comparison)
- [Firebase Blog — App Hosting vs Hosting 哪一個適合你？](https://firebase.blog/posts/2024/05/app-hosting-vs-hosting/)
- [Firebase 官方文件 — Firestore Security Rules Conditions](https://firebase.google.com/docs/firestore/security/rules-conditions)
- [Firebase 官方文件 — Firestore Best Practices](https://firebase.google.com/docs/firestore/best-practices)
- [Firebase Blog — Cloud Next 2026 公告](https://firebase.blog/posts/2026/04/cloud-next-2026-announcements)
- [Genkit GitHub Repository](https://github.com/genkit-ai/genkit)
- [Horizon Dev — Supabase vs Firebase 2026 startup 評測](https://horizon.dev/blog/supabase-vs-firebase-startups/)
- [Tech Insider — Supabase vs Firebase 2026 三倍成本差距實測](https://tech-insider.org/supabase-vs-firebase-2026-2/)
- [GPU Per Hour — 43+ 雲端供應商 Egress 定價總覽](https://gpuperhour.com/reference/data-egress)
- [Java Code Geeks — Firebase Functions 冷啟動深度分析](https://www.javacodegeeks.com/2025/04/comprehensive-analysis-of-firebase-functions-cold-starts.html)

---

**這篇對你有幫助嗎？** 如果你正在評估技術選型、或處理 Firebase 帳單失控的問題，歡迎留言分享你的踩坑經驗。下一篇我會寫「Firebase → Supabase 實戰遷移指南」，帶你看真實案例怎麼把 Firestore 結構翻譯成 PostgreSQL schema、Security Rules 改寫成 RLS。
