Hello World - 实时聊天消息

知识库
知识库文档
/tech-stacks/firestore/examples/Hello World - 实时聊天消息.md

文档

Firestore Hello World:实时聊天消息

目标

连接 Firestore,创建聊天消息集合并实现实时监听——新增消息自动出现在客户端。

完整代码

Web 版 (JavaScript)

<!DOCTYPE html>
<html>
<head>
    <title>Firestore 聊天室</title>
</head>
<body>
    <h2>实时聊天室</h2>
    <div id="messages" style="height:300px;overflow-y:auto;border:1px solid #ccc;padding:10px;margin-bottom:10px;"></div>
    <input id="msgInput" placeholder="输入消息..." style="width:300px;">
    <button onclick="sendMessage()">发送</button>

    <script type="module">
        import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-app.js';
        import { getFirestore, collection, addDoc, query, orderBy, limit, onSnapshot, serverTimestamp } from 'https://www.gstatic.com/firebasejs/10.12.0/firebase-firestore.js';

        // == 1. 初始化 ==
        const firebaseConfig = {
            apiKey: "YOUR_API_KEY",
            authDomain: "YOUR_PROJECT.firebaseapp.com",
            projectId: "YOUR_PROJECT_ID",
        };
        const app = initializeApp(firebaseConfig);
        const db = getFirestore(app);

        // == 2. 发送消息 ==
        window.sendMessage = async function() {
            const input = document.getElementById('msgInput');
            const text = input.value.trim();
            if (!text) return;

            await addDoc(collection(db, 'messages'), {
                text: text,
                user: '匿名用户',
                createdAt: serverTimestamp()
            });
            input.value = '';
        };

        // == 3. 实时监听 ==
        const messagesRef = collection(db, 'messages');
        const q = query(messagesRef, orderBy('createdAt', 'desc'), limit(50));

        onSnapshot(q, (snapshot) => {
            const container = document.getElementById('messages');
            container.innerHTML = '';
            snapshot.docChanges().forEach(change => {
                if (change.type === 'added') {
                    const msg = change.doc.data();
                    const div = document.createElement('div');
                    div.textContent = `[${msg.user}] ${msg.text}`;
                    container.prepend(div);
                }
            });
        });
    </script>
</body>
</html>

Node.js 版

// npm install firebase-admin
const { initializeApp, cert } = require('firebase-admin/app');
const { getFirestore, Timestamp, FieldValue } = require('firebase-admin/firestore');

initializeApp({ credential: cert('./serviceAccountKey.json') });
const db = getFirestore();

// 写入消息
async function sendMessage(user, text) {
    const docRef = await db.collection('messages').add({
        user: user,
        text: text,
        createdAt: FieldValue.serverTimestamp(),
    });
    console.log(`消息 ID: ${docRef.id}`);
    return docRef;
}

// 实时监听(服务端订阅)
function listenForMessages() {
    const unsubscribe = db.collection('messages')
        .orderBy('createdAt', 'desc')
        .limit(10)
        .onSnapshot(snapshot => {
            snapshot.docChanges().forEach(change => {
                if (change.type === 'added') {
                    const msg = change.doc.data();
                    console.log(`[新消息] ${msg.user}: ${msg.text}`);
                }
            });
        });

    // 取消监听:unsubscribe();
}

// 查询历史
async function getMessages(limit = 20) {
    const snapshot = await db.collection('messages')
        .orderBy('createdAt', 'desc')
        .limit(limit)
        .get();

    const messages = [];
    snapshot.forEach(doc => {
        messages.push({ id: doc.id, ...doc.data() });
    });
    return messages;
}

// 运行
sendMessage('Alice', '大家好!');
getMessages().then(msgs => console.log(msgs));

Python 版

# pip install firebase-admin
import firebase_admin
from firebase_admin import credentials, firestore
from google.cloud.firestore_v1 import SERVER_TIMESTAMP

cred = credentials.Certificate('./serviceAccountKey.json')
firebase_admin.initialize_app(cred)
db = firestore.client()

# 写入
doc_ref = db.collection('messages').document()
doc_ref.set({
    'user': 'Bob',
    'text': 'Hello from Python!',
    'createdAt': SERVER_TIMESTAMP
})
print(f"消息 ID: {doc_ref.id}")

# 查询
docs = db.collection('messages').order_by('createdAt', direction='DESCENDING').limit(10).stream()
for doc in docs:
    print(f"{doc.to_dict()['user']}: {doc.to_dict()['text']}")

# 实时监听(需长时间运行的脚本)
def on_snapshot(col_snapshot, changes, read_time):
    for change in changes:
        if change.type.name == 'ADDED':
            print(f"[实时] {change.document.to_dict()['user']}: {change.document.to_dict()['text']}")

col_ref = db.collection('messages')
watch = col_ref.on_snapshot(on_snapshot)
# watch.unsubscribe()  # 停止监听

预期输出

消息 ID: abc123...
[新消息] Alice: 大家好!
[新消息] Bob: Hello from Python!

// 实时监听:当有新消息时自动打印
[实时] Carol: 我也在!

关键点

  • onSnapshot 是 Firestore 的核心:变更实时推送
  • serverTimestamp() 避免客户端时间不同步
  • docChanges() 区分 add/modify/remove 事件
  • 离线数据由 SDK 自动处理,联网后同步
  • 免费层足够学习使用(每日 5 万读 / 2 万写)

信息

路径
/tech-stacks/firestore/examples/Hello World - 实时聊天消息.md
更新时间
2026/5/31