> For the complete documentation index, see [llms.txt](https://developers-apps-in-toss.toss.im/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers-apps-in-toss.toss.im/ai-vibe-coding/zh/integration/ji-cheng-firebase.md).

# 集成 Firebase

介绍如何在 Appintos（迷你应用）Webview 环境中集成 Firebase。本文档 **基于 Vite（React + TypeScript）** 项目编写。

***

### 概述

Firebase 是提供认证、数据库、文件存储等多种功能的服务。在 Appintos WebView 环境中也可以同样使用，但 **安全设置和环境变量管理**很重要。

***

### 1. 准备工作

* Firebase 控制台账号（[console.firebase.google.com](https://console.firebase.google.com))
* 使用 Vite（React + TypeScript）制作的项目
* Node.js、npm（或 yarn、pnpm）

### 2. 创建 Firebase 项目

1. 在 Firebase 控制台中 **创建项目**，新建一个项目。
2. 项目设置 → **添加应用** → **Web（\</>）** 。
3. 输入应用昵称并注册后，如下所示会显示配置信息（firebaseConfig）。

```js
const firebaseConfig = {
  apiKey: '...',
  authDomain: '...',
  databaseURL: '...',
  projectId: '...',
  storageBucket: '...',
  messagingSenderId: '...',
  appId: '...',
  measurementId: '...'
}
```

### 3. 设置环境变量

建议将 Firebase 配置信息作为 Vite 环境变量来管理，以确保安全。

在项目根目录中 `.env` 创建文件，并按如下方式编写。

```bash
VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
VITE_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
VITE_FIREBASE_APP_ID=your_app_id
```

在代码中 `import.meta.env.VITE_FIREBASE_API_KEY`这样读取。

### 4. 安装并初始化 Firebase

本文基于最新的 Firebase 模块化 SDK（v12+）编写。

```bash
npm install firebase
# 或者
yarn add firebase
```

`src/firebase/init.ts`

```ts
import { initializeApp, getApps } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore'
import { getStorage } from 'firebase/storage'

const firebaseConfig = {
  apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
  authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
  projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
  storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
  appId: import.meta.env.VITE_FIREBASE_APP_ID,
}

const app = getApps().length ? getApps()[0] : initializeApp(firebaseConfig)

export const auth = getAuth(app)
export const db = getFirestore(app)
export const storage = getStorage(app)
```

> **注意：**
>
> * `databaseURL`仅在 **Realtime Database**时才需要。如果使用 Firestore，可以省略。
> * `measurementId`在 **Firebase Analytics**（Google Analytics）时需要。

### 5. Firestore 使用示例

如果初始化了 Firestore，就可以在 React 组件中读取或写入数据。下面是 `App.tsx`中读取并保存单个文档的最简单示例。

```tsx
import { useState, useEffect } from 'react'
import { db } from './firebase/init'
import { doc, getDoc, setDoc } from 'firebase/firestore'

function App() {
  const [name, setName] = useState('')
  const [savedName, setSavedName] = useState('')

  // 从 Firestore 读取数据
  useEffect(() => {
    const fetchData = async () => {
      const ref = doc(db, 'users', 'exampleUser')
      const snap = await getDoc(ref)
      if (snap.exists()) {
        setSavedName(snap.data().name)
      }
    }
    fetchData()
  }, [])

  // 向 Firestore 写入数据
  const handleSave = async () => {
    const ref = doc(db, 'users', 'exampleUser')
    await setDoc(ref, { name })
    setSavedName(name)
    setName('')
  }

  return (
    <div style={{ padding: 24 }}>
      <h1>Firestore 简单示例</h1>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="输入姓名"
      />
      <button onClick={handleSave}>保存</button>
      <p>已保存的姓名：{savedName || '(无)'}</p>

  )
}

export default App

```

#### 工作方式

* 读取数据（`getDoc`)
  * 只会加载一次 Firestore 中的 users/exampleUser 文档。
  * 如果文档存在，就把 snap.data() 的值显示在页面上。
* 写入数据（`setDoc`)
  * 将输入的姓名覆盖写入 Firestore。
  * 如果文档不存在，会自动新建。

<figure><img src="/files/33e1c43a088870bfaa96eda4f1643085657e3f4d" alt=""><figcaption></figcaption></figure>

> Firestore 除了单个文档外，还支持多种功能。
>
> * 实时订阅： `onSnapshot(doc(...))`，每当文档发生变化时，UI 会自动更新。
> * 处理集合： `collection()`, `addDoc()`，可用于添加和读取多个文档。
> * 文件存储： `getStorage()`与 `Storage`连接后，可以上传图片或文件。
> * 认证联动： `getAuth()`配合使用后，可以实现按用户保存数据。

### 6. 安全检查清单

* 将敏感信息作为环境变量管理
  * Firebase API Key、服务账号密钥等不要直接写在代码中， `.env`来管理。
* 不要把环境文件上传到 Git 等仓库
  * `.env` 文件必须添加到 `.gitignore`中。
  * 如果密钥泄露，请立即在 Firebase 控制台重新签发，并检查相关项目权限。
* 设置 Firebase 安全规则
  * Firestore / Storage 默认对所有用户开放。
  * 发布前务必修改规则，只允许已认证用户访问。
* 确认来源（Origin）限制
  * 在 Firebase 控制台的 Authentication / Hosting / API Key 设置中限制允许的域名。
  * 只允许迷你应用（WebView）域名，可以防止未授权访问。

{% hint style="info" %}
**允许的目标域名**

```
https://<appName>.apps.tossmini.com：实际服务环境
https://<appName>.private-apps.tossmini.com：控制台 QR 测试环境
```

{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers-apps-in-toss.toss.im/ai-vibe-coding/zh/integration/ji-cheng-firebase.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
