firebase-app-platform

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Firebase App Platform

Firebase应用平台

Ship mobile and web backends with Firebase managed services.
借助Firebase托管服务交付移动和网页后端。

When to Use This Skill

何时使用此技能

Use this skill when:
  • Building mobile or web apps with real-time data sync
  • Need authentication with minimal backend code
  • Prototyping quickly with managed infrastructure
  • Building serverless APIs with Cloud Functions
  • Hosting static sites or SPAs with CDN
在以下场景使用此技能:
  • 构建具备实时数据同步功能的移动或网页应用
  • 需要用最少的后端代码实现认证功能
  • 借助托管基础设施快速原型开发
  • 使用Cloud Functions构建无服务器API
  • 通过CDN托管静态站点或单页应用(SPA)

Prerequisites

前提条件

  • Node.js 18+
  • Firebase CLI (
    npm install -g firebase-tools
    )
  • Google Cloud account (Firebase is part of GCP)
  • A Firebase project (create at console.firebase.google.com)
  • Node.js 18+
  • Firebase CLI (
    npm install -g firebase-tools
    )
  • Google Cloud账号(Firebase是GCP的一部分)
  • 一个Firebase项目(在console.firebase.google.com创建)

Quick Start

快速开始

bash
undefined
bash
undefined

Install and authenticate

安装并认证

npm install -g firebase-tools firebase login
npm install -g firebase-tools firebase login

Initialize in your project directory

在项目目录中初始化

firebase init
firebase init

Select: Firestore, Functions, Hosting, Emulators

选择:Firestore、Functions、Hosting、Emulators

Start local emulators

启动本地模拟器

firebase emulators:start
firebase emulators:start

Deploy everything

部署所有服务

firebase deploy
firebase deploy

Deploy specific services

部署特定服务

firebase deploy --only functions firebase deploy --only hosting firebase deploy --only firestore:rules
undefined
firebase deploy --only functions firebase deploy --only hosting firebase deploy --only firestore:rules
undefined

Firestore Database

Firestore数据库

Security Rules

安全规则

javascript
// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Users can only read/write their own data
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }

    // Messages: authenticated users can read, only owner can write
    match /channels/{channelId}/messages/{messageId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null
        && request.resource.data.userId == request.auth.uid
        && request.resource.data.body is string
        && request.resource.data.body.size() <= 5000;
      allow update, delete: if request.auth != null
        && resource.data.userId == request.auth.uid;
    }

    // Admin-only collection
    match /admin/{document=**} {
      allow read, write: if request.auth != null
        && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
    }

    // Default: deny everything
    match /{document=**} {
      allow read, write: if false;
    }
  }
}
javascript
// firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // 用户仅能读写自己的数据
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }

    // 消息:已认证用户可读取,仅所有者可写入
    match /channels/{channelId}/messages/{messageId} {
      allow read: if request.auth != null;
      allow create: if request.auth != null
        && request.resource.data.userId == request.auth.uid
        && request.resource.data.body is string
        && request.resource.data.body.size() <= 5000;
      allow update, delete: if request.auth != null
        && resource.data.userId == request.auth.uid;
    }

    // 仅管理员可访问的集合
    match /admin/{document=**} {
      allow read, write: if request.auth != null
        && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';
    }

    // 默认:拒绝所有操作
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Data Operations

数据操作

typescript
// lib/firestore.ts
import { getFirestore, collection, doc, setDoc, getDoc,
         query, where, orderBy, limit, onSnapshot,
         serverTimestamp, increment } from "firebase/firestore";

const db = getFirestore();

// Create document with auto-ID
async function createMessage(channelId: string, body: string, userId: string) {
  const ref = doc(collection(db, "channels", channelId, "messages"));
  await setDoc(ref, {
    body,
    userId,
    createdAt: serverTimestamp(),
  });
  return ref.id;
}

// Real-time listener
function subscribeToMessages(channelId: string, callback: (msgs: any[]) => void) {
  const q = query(
    collection(db, "channels", channelId, "messages"),
    orderBy("createdAt", "desc"),
    limit(50)
  );
  return onSnapshot(q, (snapshot) => {
    const messages = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    callback(messages);
  });
}

// Atomic counter
async function incrementViews(postId: string) {
  await setDoc(doc(db, "posts", postId), {
    views: increment(1),
  }, { merge: true });
}
typescript
// lib/firestore.ts
import { getFirestore, collection, doc, setDoc, getDoc,
         query, where, orderBy, limit, onSnapshot,
         serverTimestamp, increment } from "firebase/firestore";

const db = getFirestore();

// 创建带自动ID的文档
async function createMessage(channelId: string, body: string, userId: string) {
  const ref = doc(collection(db, "channels", channelId, "messages"));
  await setDoc(ref, {
    body,
    userId,
    createdAt: serverTimestamp(),
  });
  return ref.id;
}

// 实时监听器
function subscribeToMessages(channelId: string, callback: (msgs: any[]) => void) {
  const q = query(
    collection(db, "channels", channelId, "messages"),
    orderBy("createdAt", "desc"),
    limit(50)
  );
  return onSnapshot(q, (snapshot) => {
    const messages = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
    callback(messages);
  });
}

// 原子计数器
async function incrementViews(postId: string) {
  await setDoc(doc(db, "posts", postId), {
    views: increment(1),
  }, { merge: true });
}

Indexes

索引

json
// firestore.indexes.json
{
  "indexes": [
    {
      "collectionGroup": "messages",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "channelId", "order": "ASCENDING" },
        { "fieldPath": "createdAt", "order": "DESCENDING" }
      ]
    }
  ]
}
json
// firestore.indexes.json
{
  "indexes": [
    {
      "collectionGroup": "messages",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "channelId", "order": "ASCENDING" },
        { "fieldPath": "createdAt", "order": "DESCENDING" }
      ]
    }
  ]
}

Authentication

认证

typescript
// lib/auth.ts
import { getAuth, signInWithPopup, GoogleAuthProvider,
         createUserWithEmailAndPassword, signInWithEmailAndPassword,
         signOut, onAuthStateChanged } from "firebase/auth";

const auth = getAuth();

// Google sign-in
async function signInWithGoogle() {
  const provider = new GoogleAuthProvider();
  const result = await signInWithPopup(auth, provider);
  return result.user;
}

// Email/password registration
async function register(email: string, password: string) {
  const result = await createUserWithEmailAndPassword(auth, email, password);
  return result.user;
}

// Auth state listener
onAuthStateChanged(auth, (user) => {
  if (user) {
    console.log("Signed in:", user.uid, user.email);
  } else {
    console.log("Signed out");
  }
});
typescript
// lib/auth.ts
import { getAuth, signInWithPopup, GoogleAuthProvider,
         createUserWithEmailAndPassword, signInWithEmailAndPassword,
         signOut, onAuthStateChanged } from "firebase/auth";

const auth = getAuth();

// Google登录
async function signInWithGoogle() {
  const provider = new GoogleAuthProvider();
  const result = await signInWithPopup(auth, provider);
  return result.user;
}

// 邮箱/密码注册
async function register(email: string, password: string) {
  const result = await createUserWithEmailAndPassword(auth, email, password);
  return result.user;
}

// 认证状态监听器
onAuthStateChanged(auth, (user) => {
  if (user) {
    console.log("已登录:", user.uid, user.email);
  } else {
    console.log("已登出");
  }
});

Cloud Functions

Cloud Functions

typescript
// functions/src/index.ts
import { onRequest } from "firebase-functions/v2/https";
import { onDocumentCreated } from "firebase-functions/v2/firestore";
import { getFirestore } from "firebase-admin/firestore";
import { initializeApp } from "firebase-admin/app";

initializeApp();
const db = getFirestore();

// HTTP function (API endpoint)
export const api = onRequest({ cors: true, region: "us-central1" }, async (req, res) => {
  if (req.method !== "GET") {
    res.status(405).send("Method not allowed");
    return;
  }
  const snapshot = await db.collection("posts").orderBy("createdAt", "desc").limit(10).get();
  const posts = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
  res.json({ posts });
});

// Firestore trigger — runs when a new message is created
export const onMessageCreated = onDocumentCreated(
  "channels/{channelId}/messages/{messageId}",
  async (event) => {
    const data = event.data?.data();
    if (!data) return;

    // Update channel's last message timestamp
    await db.doc(`channels/${event.params.channelId}`).update({
      lastMessageAt: data.createdAt,
      messageCount: FieldValue.increment(1),
    });

    // Send notification (example)
    console.log(`New message in ${event.params.channelId}: ${data.body.substring(0, 50)}`);
  }
);
typescript
// functions/src/index.ts
import { onRequest } from "firebase-functions/v2/https";
import { onDocumentCreated } from "firebase-functions/v2/firestore";
import { getFirestore } from "firebase-admin/firestore";
import { initializeApp } from "firebase-admin/app";

initializeApp();
const db = getFirestore();

// HTTP函数(API端点)
export const api = onRequest({ cors: true, region: "us-central1" }, async (req, res) => {
  if (req.method !== "GET") {
    res.status(405).send("方法不允许");
    return;
  }
  const snapshot = await db.collection("posts").orderBy("createdAt", "desc").limit(10).get();
  const posts = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
  res.json({ posts });
});

// Firestore触发器 — 新消息创建时运行
export const onMessageCreated = onDocumentCreated(
  "channels/{channelId}/messages/{messageId}",
  async (event) => {
    const data = event.data?.data();
    if (!data) return;

    // 更新频道的最后消息时间戳
    await db.doc(`channels/${event.params.channelId}`).update({
      lastMessageAt: data.createdAt,
      messageCount: FieldValue.increment(1),
    });

    // 发送通知(示例)
    console.log(`频道${event.params.channelId}收到新消息: ${data.body.substring(0, 50)}`);
  }
);

Hosting

托管

json
// firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      { "source": "/api/**", "function": "api" },
      { "source": "**", "destination": "/index.html" }
    ],
    "headers": [
      {
        "source": "**/*.@(js|css|svg|png|jpg|webp|woff2)",
        "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
      },
      {
        "source": "**",
        "headers": [
          { "key": "X-Frame-Options", "value": "DENY" },
          { "key": "X-Content-Type-Options", "value": "nosniff" },
          { "key": "Strict-Transport-Security", "value": "max-age=63072000" }
        ]
      }
    ]
  }
}
json
// firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      { "source": "/api/**", "function": "api" },
      { "source": "**", "destination": "/index.html" }
    ],
    "headers": [
      {
        "source": "**/*.@(js|css|svg|png|jpg|webp|woff2)",
        "headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
      },
      {
        "source": "**",
        "headers": [
          { "key": "X-Frame-Options", "value": "DENY" },
          { "key": "X-Content-Type-Options", "value": "nosniff" },
          { "key": "Strict-Transport-Security", "value": "max-age=63072000" }
        ]
      }
    ]
  }
}

Local Emulators

本地模拟器

bash
undefined
bash
undefined

Start all emulators

启动所有模拟器

firebase emulators:start
firebase emulators:start

Start specific emulators

启动特定模拟器

firebase emulators:start --only auth,firestore,functions
firebase emulators:start --only auth,firestore,functions

Export emulator data for persistence

导出模拟器数据以持久化

firebase emulators:export ./emulator-data firebase emulators:start --import=./emulator-data
firebase emulators:export ./emulator-data firebase emulators:start --import=./emulator-data

Emulator UI at http://localhost:4000

模拟器UI地址:http://localhost:4000


```json
// firebase.json — emulator config
{
  "emulators": {
    "auth": { "port": 9099 },
    "firestore": { "port": 8080 },
    "functions": { "port": 5001 },
    "hosting": { "port": 5000 },
    "ui": { "enabled": true, "port": 4000 }
  }
}

```json
// firebase.json — 模拟器配置
{
  "emulators": {
    "auth": { "port": 9099 },
    "firestore": { "port": 8080 },
    "functions": { "port": 5001 },
    "hosting": { "port": 5000 },
    "ui": { "enabled": true, "port": 4000 }
  }
}

Environment Configuration

环境配置

bash
undefined
bash
undefined

Set environment variables for functions

为函数设置环境变量

firebase functions:config:set stripe.key="sk_live_xxx" app.name="MyApp"
firebase functions:config:set stripe.key="sk_live_xxx" app.name="MyApp"

View config

查看配置

firebase functions:config:get
firebase functions:config:get

Use in functions (v1)

在函数中使用(v1版本)

const stripeKey = functions.config().stripe.key;
const stripeKey = functions.config().stripe.key;

For v2 functions, use .env files

对于v2函数,使用.env文件

functions/.env

functions/.env

STRIPE_KEY=sk_live_xxx
STRIPE_KEY=sk_live_xxx

functions/.env.local (for emulators)

functions/.env.local(用于模拟器)

STRIPE_KEY=sk_test_xxx
undefined
STRIPE_KEY=sk_test_xxx
undefined

Multi-Environment Setup

多环境设置

bash
undefined
bash
undefined

Create separate projects for each environment

为每个环境创建独立项目

firebase use --add # Add staging project alias firebase use staging # Switch to staging firebase use production
firebase use --add # 添加预发布项目别名 firebase use staging # 切换到预发布环境 firebase use production

Deploy to specific project

部署到特定项目

firebase deploy --project my-app-staging firebase deploy --project my-app-production
firebase deploy --project my-app-staging firebase deploy --project my-app-production

.firebaserc

.firebaserc

{ "projects": { "staging": "my-app-staging", "production": "my-app-production" } }
undefined
{ "projects": { "staging": "my-app-staging", "production": "my-app-production" } }
undefined

CLI Reference

CLI参考

bash
firebase projects:list              # List all projects
firebase deploy                      # Deploy everything
firebase deploy --only functions     # Deploy only functions
firebase deploy --only hosting       # Deploy only hosting
firebase deploy --only firestore     # Deploy rules + indexes
firebase functions:log               # View function logs
firebase hosting:channel:create pr-123  # Preview channel
firebase hosting:channel:delete pr-123
bash
firebase projects:list              # 列出所有项目
firebase deploy                      # 部署所有服务
firebase deploy --only functions     # 仅部署函数
firebase deploy --only hosting       # 仅托管部署
firebase deploy --only firestore     # 部署规则和索引
firebase functions:log               # 查看函数日志
firebase hosting:channel:create pr-123  # 创建预览频道
firebase hosting:channel:delete pr-123

Security Best Practices

安全最佳实践

  • Write strict Firestore security rules before any other code
  • Separate environments by Firebase project (staging/production)
  • Enable budget alerts and quota monitoring in GCP console
  • Move privileged logic into Cloud Functions (never trust the client)
  • Use App Check to prevent API abuse from non-app clients
  • Enable Firestore audit logging for compliance
  • Review OAuth consent screen settings
  • 在编写任何其他代码之前,先编写严格的Firestore安全规则
  • 通过Firebase项目分离环境(预发布/生产)
  • 在GCP控制台中启用预算警报和配额监控
  • 将特权逻辑移至Cloud Functions(绝不信任客户端)
  • 使用App Check防止非应用客户端滥用API
  • 启用Firestore审计日志以符合合规要求
  • 审核OAuth同意屏幕设置

Troubleshooting

故障排除

IssueSolution
Permission deniedCheck Firestore rules, verify auth state
Function cold startsUse min instances (
minInstances: 1
), optimize imports
Emulator won't startCheck port conflicts, run
firebase emulators:start --debug
Deploy failsRun
firebase deploy --debug
, check service account permissions
Rules test failingUse
firebase emulators:exec
to run rules unit tests
问题解决方案
权限被拒绝检查Firestore规则,验证认证状态
函数冷启动使用最小实例数(
minInstances: 1
),优化导入
模拟器无法启动检查端口冲突,运行
firebase emulators:start --debug
部署失败运行
firebase deploy --debug
,检查服务账号权限
规则测试失败使用
firebase emulators:exec
运行规则单元测试

Related Skills

相关技能

  • gcp-cloud-functions — Function runtime patterns
  • vercel-deployments — Alternative frontend hosting
  • convex-backend — Alternative managed backend
  • gcp-cloud-functions — 函数运行时模式
  • vercel-deployments — 替代前端托管方案
  • convex-backend — 替代托管后端方案