
Installiere firebase und vuefire, initialisiere die Anwendung mit initializeApp und getFirestore und lies eine Sammlung dann mit useCollection: Die Liste aktualisiert sich von selbst. Entwickle gegen den lokalen Firestore-Emulator statt gegen das Produktionsprojekt.
Firebase liefert Datenbank, Authentifizierung und Hosting, ohne dass du dafür Server-Code schreibst. An Vue angeschlossen, ergibt das eine Echtzeitdatenbank, deren Änderungen von selbst in der Oberfläche ankommen. So verkabelst du beides sauber mit dem modularen SDK.
Firestore oder Realtime Database?
Firebase bietet zwei Datenbanken an. Realtime Database ist die ältere: ein großer JSON-Baum mit begrenzten Abfragen. Cloud Firestore organisiert die Daten in Sammlungen von Dokumenten, kennt echte zusammengesetzte Abfragen und Indizes. Für ein neues Projekt nimmst du Firestore, genau das macht dieser Artikel.
Installieren
npm install firebase vuefireVueFire ist die offizielle Schicht, die Firebase an die Reaktivität von Vue anbindet. Pflicht ist sie nicht, aber sie erspart dir, die Abonnements und ihr Aufräumen von Hand zu schreiben.
Initialisieren
Leg das Projekt in der Firebase-Konsole an, füge eine Web-App hinzu und kopiere die Konfiguration. Sie gehört in eine eigene Datei:
import { initializeApp } from 'firebase/app'
import { getFirestore } from 'firebase/firestore'
export const firebaseApp = initializeApp({
apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
authDomain: 'mon-projet.firebaseapp.com',
projectId: 'mon-projet'
})
export const db = getFirestore(firebaseApp)Anders als der Name nahelegt, ist er kein Geheimnis: Er landet im JavaScript-Bundle und jeder kann ihn lesen. Er identifiziert das Projekt, er autorisiert es nicht. Die Sicherheit hängt vollständig an den Firestore-Regeln und der Authentifizierung. Diese Regeln zu schreiben ist die eigentliche Sicherheitsarbeit, nicht das Verstecken des Schlüssels.
Danach hängst du VueFire an die Anwendung:
import { createApp } from 'vue'
import { VueFire } from 'vuefire'
import App from './App.vue'
import { firebaseApp } from './firebase'
createApp(App)
.use(VueFire, { firebaseApp })
.mount('#app')Eine Sammlung lesen
useCollection gibt eine reaktive Referenz zurück, die Firestore befüllt und anschließend aktuell hält:
<script setup>
import { collection } from 'firebase/firestore'
import { useCollection } from 'vuefire'
import { db } from '@/firebase'
const avis = useCollection(collection(db, 'avis'))
</script>
<template>
<ul>
<li v-for="a in avis" :key="a.id">{{ a.nom }} : {{ a.note }}/5</li>
</ul>
</template>Das ist alles: Die Schleife v-for zeigt die Sammlung wie jedes andere Array an. Öffne die Firebase-Konsole und ändere ein Dokument: Die Liste ändert sich im Browser ohne Neuladen. VueFire schließt das Abonnement beim Unmount der Komponente, was das klassische Leck durch vergessene Listener verhindert.
Für ein einzelnes Dokument folgt useDocument derselben Logik:
import { doc } from 'firebase/firestore'
import { useDocument } from 'vuefire'
const produit = useDocument(doc(db, 'produits', '2234'))Filtern und sortieren
Abfragen setzt du aus query, where, orderBy und limit zusammen:
import { collection, limit, orderBy, query, where } from 'firebase/firestore'
const meilleursAvis = useCollection(
query(
collection(db, 'avis'),
where('note', '>=', 4),
orderBy('note', 'desc'),
limit(10)
)
)Eine Abfrage, die einen Filter und eine Sortierung auf verschiedenen Feldern kombiniert, braucht einen zusammengesetzten Index. Firestore verweigert die Abfrage und zeigt in der Konsole einen Link an, der den Index mit einem Klick anlegt, das ist die nützlichste Fehlermeldung des Produkts.
Schreiben
Schreibzugriffe laufen über die Funktionen des SDK, nicht über VueFire. Häng sie an ein Formular, um Dokumente aus der Oberfläche heraus anzulegen:
import {
addDoc, collection, deleteDoc, doc, serverTimestamp, setDoc, updateDoc
} from 'firebase/firestore'
import { db } from '@/firebase'
// von Firestore erzeugte ID
await addDoc(collection(db, 'avis'), {
nom: 'Damien',
note: 5,
creeLe: serverTimestamp()
})
// selbst gewählte ID (legt an oder ersetzt)
await setDoc(doc(db, 'avis', 'avis-2234'), { nom: 'Damien', note: 5 })
// einzelne Felder ändern
await updateDoc(doc(db, 'avis', 'avis-2234'), { note: 4 })
// löschen
await deleteDoc(doc(db, 'avis', 'avis-2234'))serverTimestamp() überlässt den Zeitstempel dem Server: Die Uhr auf dem Rechner der Besucherin ist nicht verlässlich.
Gegen den Emulator entwickeln
Direkt auf dem Produktionsprojekt zu arbeiten, verdirbt die Daten und frisst das Kontingent. Die Firebase-Emulator-Suite lässt Firestore lokal laufen.
npm install -D firebase-tools
npx firebase init emulators # Firestore ankreuzen
npx firebase emulators:start --only firestore --project demo-boutiqueEine Projekt-ID, die mit demo- beginnt, sagt dem Emulator, dass er ohne Konto und ohne Abrechnung arbeiten soll.
Auf Seiten der Anwendung verbindest du das SDK nur in der Entwicklung mit dem Emulator:
import { connectFirestoreEmulator, getFirestore } from 'firebase/firestore'
export const db = getFirestore(firebaseApp)
if (import.meta.env.DEV) {
connectFirestoreEmulator(db, '127.0.0.1', 8080)
}Seit firebase-tools 15 lässt eine ältere JDK-Version den Start mit der Meldung „firebase-tools no longer supports Java version before 21“ scheitern. Prüf das mit java -version.
Die Sicherheitsregeln
Ohne Regeln ist die Datenbank entweder dicht oder für alle offen. Der beim Anlegen vorgeschlagene „Test“-Modus läuft nach dreißig Tagen ab, lass ihn nicht in Produktion stehen.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /avis/{avisId} {
// öffentlicher Lesezugriff
allow read: if true;
// Schreibzugriff nur für angemeldete Personen, auf ihre eigene Bewertung
allow create: if request.auth != null
&& request.resource.data.auteurId == request.auth.uid;
allow update, delete: if request.auth != null
&& resource.data.auteurId == request.auth.uid;
}
}
}Auch die Regeln lassen sich gegen den Emulator schreiben und testen, statt ein Loch erst in Produktion zu entdecken.
Was sich seit SDK 8 geändert hat
Viele Beispiele, die noch online stehen, benutzen die alte Namespace-API. Seit Firebase 9 funktioniert sie so nicht mehr:
// altes SDK (8 und älter) — funktioniert nicht mehr
import firebase from 'firebase'
const db = firebase.initializeApp(config).database()
db.ref('avis').push({ nom: 'Damien' })
// modulares SDK (9 und neuer)
import { initializeApp } from 'firebase/app'
import { addDoc, collection, getFirestore } from 'firebase/firestore'
const db = getFirestore(initializeApp(config))
await addDoc(collection(db, 'avis'), { nom: 'Damien' })Die Aufteilung in importierte Funktionen ist keine Kosmetik: Sie erlaubt dem Bundler, nur das zu behalten, was du auch benutzt. Bei einer Anwendung, die Firestore nur liest, ist der Größenunterschied deutlich.
Bei VueFire sind die alte Option firebase: { … } in den Komponenten und das Objekt $firebaseRefs verschwunden: Alles läuft über useCollection und useDocument.
Weiterlesen
Dieser Aufbau setzt Komponenten und Reaktivität in Vue voraus. Wenn dir das fehlt, fang mit dem Vue-3-Tutorial für Einsteiger an. Um Firebase-Daten zwischen weit auseinanderliegenden Komponenten zu teilen, ist ein Pinia-Store, der die Firestore-Aufrufe kapselt, ein gutes Muster.
Häufige Fehler
firebase.initializeApp(config).database() und das globale Objekt firebase funktionieren seit Version 9 nicht mehr. Alles läuft über importierte Funktionen.firebase: { … } in den Komponenten und $firebaseRefs sind verschwunden: Nimm useCollection und useDocument.

