
Zainstaluj firebase i vuefire, zainicjuj aplikację przez initializeApp i getFirestore, a potem odczytaj kolekcję przez useCollection: lista aktualizuje się sama. Pracuj na lokalnym emulatorze Firestore, a nie na projekcie produkcyjnym.
Firebase daje bazę danych, uwierzytelnianie i hosting, bez pisania własnego backendu. Podpięty pod Vue, zachowuje się jak baza czasu rzeczywistego, której zmiany same przechodzą do interfejsu. Oto jak połączyć jedno z drugim porządnie, na modularnym SDK.
Firestore czy Realtime Database?
Firebase oferuje dwie bazy. Realtime Database jest starsza: jedno wielkie drzewo JSON i mocno ograniczone zapytania. Cloud Firestore układa dane w kolekcje dokumentów, obsługuje prawdziwe zapytania złożone i indeksy. Do nowego projektu bierz Firestore, i na nim opiera się ten artykuł.
Instalacja
npm install firebase vuefireVueFire to oficjalna warstwa spinająca Firebase z reaktywnością Vue. Nie jest obowiązkowa, ale oszczędza ręcznego pisania subskrypcji i ich sprzątania.
Inicjalizacja
Załóż projekt w konsoli Firebase, dodaj aplikację webową i skopiuj konfigurację. Trzymaj ją w osobnym pliku:
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)Wbrew temu, co sugeruje nazwa, to nie jest sekret: trafia do bundle’a JavaScriptu i każdy może go odczytać. Identyfikuje projekt, ale niczego nie autoryzuje. Bezpieczeństwo opiera się w całości na regułach Firestore i uwierzytelnianiu. Prawdziwą robotą jest napisanie reguł, a nie ukrywanie tego klucza.
Następnie podepnij VueFire do aplikacji:
import { createApp } from 'vue'
import { VueFire } from 'vuefire'
import App from './App.vue'
import { firebaseApp } from './firebase'
createApp(App)
.use(VueFire, { firebaseApp })
.mount('#app')Odczyt kolekcji
useCollection zwraca reaktywną referencję, którą Firestore najpierw zasila, a potem utrzymuje w aktualności:
<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>I to wszystko: pętla v-for wyświetla kolekcję jak zwykłą tablicę. Otwórz konsolę Firebase i zmień dokument, lista zmieni się w przeglądarce bez przeładowania. VueFire zamyka subskrypcję przy odmontowaniu komponentu, więc odpada klasyczny wyciek z zapomnianych listenerów.
Dla pojedynczego dokumentu useDocument działa tak samo:
import { doc } from 'firebase/firestore'
import { useDocument } from 'vuefire'
const produit = useDocument(doc(db, 'produits', '2234'))Filtrowanie i sortowanie
Zapytania składa się z query, where, orderBy i limit:
import { collection, limit, orderBy, query, where } from 'firebase/firestore'
const meilleursAvis = useCollection(
query(
collection(db, 'avis'),
where('note', '>=', 4),
orderBy('note', 'desc'),
limit(10)
)
)Zapytanie, które łączy filtr i sortowanie po różnych polach, wymaga indeksu złożonego. Firestore je odrzuci i wypisze w konsoli link tworzący ten indeks jednym kliknięciem, to najbardziej użyteczny komunikat błędu w całym produkcie.
Zapis
Zapisy idą przez funkcje SDK, nie przez VueFire. Podepnij je pod formularz, żeby tworzyć dokumenty z poziomu interfejsu:
import {
addDoc, collection, deleteDoc, doc, serverTimestamp, setDoc, updateDoc
} from 'firebase/firestore'
import { db } from '@/firebase'
// identyfikator wygenerowany przez Firestore
await addDoc(collection(db, 'avis'), {
nom: 'Damien',
note: 5,
creeLe: serverTimestamp()
})
// identyfikator wybrany ręcznie (tworzy albo nadpisuje)
await setDoc(doc(db, 'avis', 'avis-2234'), { nom: 'Damien', note: 5 })
// zmiana wybranych pól
await updateDoc(doc(db, 'avis', 'avis-2234'), { note: 4 })
// usunięcie
await deleteDoc(doc(db, 'avis', 'avis-2234'))serverTimestamp() zostawia stemplowanie czasem po stronie serwera: zegar maszyny odwiedzającego nie jest wiarygodny.
Praca na emulatorze
Praca wprost na projekcie produkcyjnym psuje dane i zjada limity. Pakiet emulatorów Firebase uruchamia Firestore lokalnie.
npm install -D firebase-tools
npx firebase init emulators # zaznacz Firestore
npx firebase emulators:start --only firestore --project demo-boutiqueIdentyfikator projektu zaczynający się od demo- mówi emulatorowi, żeby działał bez konta i bez rozliczeń.
Po stronie aplikacji podłącz SDK do emulatora wyłącznie w trybie deweloperskim:
import { connectFirestoreEmulator, getFirestore } from 'firebase/firestore'
export const db = getFirestore(firebaseApp)
if (import.meta.env.DEV) {
connectFirestoreEmulator(db, '127.0.0.1', 8080)
}Od firebase-tools 15 starszy JDK wywala start komunikatem „firebase-tools no longer supports Java version before 21”. Sprawdź przez java -version.
Reguły bezpieczeństwa
Bez reguł baza jest albo zamknięta, albo otwarta dla wszystkich. Tryb testowy proponowany przy zakładaniu projektu wygasa po trzydziestu dniach, nie zostawiaj go na produkcji.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /avis/{avisId} {
// odczyt publiczny
allow read: if true;
// zapis tylko dla zalogowanych, na własnej opinii
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;
}
}
}Reguły też pisze się i testuje na emulatorze, dzięki czemu dziury nie odkrywasz dopiero na produkcji.
Co się zmieniło od SDK 8
Sporo krążących po sieci przykładów wciąż korzysta ze starego API z przestrzeniami nazw. Od Firebase 9 taki kod po prostu nie działa:
// stary SDK (8 i starsze) — już nie działa
import firebase from 'firebase'
const db = firebase.initializeApp(config).database()
db.ref('avis').push({ nom: 'Damien' })
// modularny SDK (9 i nowsze)
import { initializeApp } from 'firebase/app'
import { addDoc, collection, getFirestore } from 'firebase/firestore'
const db = getFirestore(initializeApp(config))
await addDoc(collection(db, 'avis'), { nom: 'Damien' })Rozbicie na importowane funkcje nie jest kosmetyką: pozwala bundlerowi zostawić tylko to, czego naprawdę używasz. W aplikacji, która wyłącznie czyta z Firestore, różnica w wadze jest wyraźna.
Po stronie VueFire zniknęły stara opcja firebase: { … } w komponentach i obiekt $firebaseRefs: wszystko idzie przez useCollection i useDocument.
Co dalej
Ten montaż zakłada, że komponenty i reaktywność Vue masz już opanowane. Jeśli nie, zacznij od kursu Vue 3 dla początkujących. Do dzielenia danych z Firebase między odległymi komponentami dobrym wzorcem jest store Pinia, który opakowuje wywołania Firestore.
Częste błędy
firebase.initializeApp(config).database() i globalny obiekt firebase nie działają od wersji 9. Wszystko idzie przez importowane funkcje.firebase: { … } w komponentach i $firebaseRefs zniknęły: używaj useCollection i useDocument.

