
Instala firebase y vuefire, inicializa la aplicación con initializeApp y getFirestore, y luego lee una colección con useCollection: la lista se actualiza sola. Desarrolla contra el emulador local de Firestore en lugar de hacerlo sobre el proyecto de producción.
Firebase aporta una base de datos, autenticación y alojamiento sin escribir un servidor. Enchufado a Vue, da una base en tiempo real cuyos cambios se propagan solos a la interfaz. Así se cablea correctamente con el SDK modular.
¿Firestore o Realtime Database?
Firebase ofrece dos bases. Realtime Database es la más antigua: un gran árbol JSON y consultas limitadas. Cloud Firestore organiza los datos en colecciones de documentos, admite consultas compuestas de verdad e índices. Para un proyecto nuevo, elige Firestore, es lo que hace este artículo.
Instalar
npm install firebase vuefireVueFire es la capa oficial que conecta Firebase con la reactividad de Vue. No es obligatoria, pero evita escribir a mano las suscripciones y su limpieza.
Inicializar
Crea el proyecto en la consola de Firebase, añade una aplicación web y copia la configuración. Guárdala en un archivo dedicado:
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)Al contrario de lo que sugiere su nombre, no es un secreto: viaja en el bundle de JavaScript y cualquiera puede leerla. Identifica el proyecto, no lo autoriza. La seguridad descansa por completo en las reglas de Firestore y en la autenticación. Escribir esas reglas es la verdadera tarea de seguridad, no esconder la clave.
Después conecta VueFire a la aplicación:
import { createApp } from 'vue'
import { VueFire } from 'vuefire'
import App from './App.vue'
import { firebaseApp } from './firebase'
createApp(App)
.use(VueFire, { firebaseApp })
.mount('#app')Leer una colección
useCollection devuelve una referencia reactiva, que Firestore rellena y mantiene al día:
<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>Ya está: el bucle v-for muestra la colección como cualquier array. Abre la consola de Firebase y modifica un documento: la lista cambia en el navegador sin recargar. VueFire cierra la suscripción al desmontar el componente, lo que evita la fuga clásica de los listeners olvidados.
Para un documento suelto, useDocument sigue la misma lógica:
import { doc } from 'firebase/firestore'
import { useDocument } from 'vuefire'
const produit = useDocument(doc(db, 'produits', '2234'))Filtrar y ordenar
Las consultas se componen con query, where, orderBy y 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)
)
)Una consulta que combina un filtro y una ordenación sobre campos distintos exige un índice compuesto. Firestore la rechaza y muestra en la consola un enlace que crea el índice de un clic, es el mensaje de error más útil del producto.
Escribir
Las escrituras pasan por las funciones del SDK, no por VueFire. Engánchalas a un formulario para crear documentos desde la interfaz:
import {
addDoc, collection, deleteDoc, doc, serverTimestamp, setDoc, updateDoc
} from 'firebase/firestore'
import { db } from '@/firebase'
// identificador generado por Firestore
await addDoc(collection(db, 'avis'), {
nom: 'Damien',
note: 5,
creeLe: serverTimestamp()
})
// identificador elegido (crea o reemplaza)
await setDoc(doc(db, 'avis', 'avis-2234'), { nom: 'Damien', note: 5 })
// modificar algunos campos
await updateDoc(doc(db, 'avis', 'avis-2234'), { note: 4 })
// eliminar
await deleteDoc(doc(db, 'avis', 'avis-2234'))serverTimestamp() deja que Firestore ponga la marca de tiempo en el servidor: la hora de la máquina del visitante no es fiable.
Desarrollar contra el emulador
Trabajar directamente sobre el proyecto de producción estropea los datos y consume cuota. La suite de emuladores de Firebase ejecuta Firestore en local.
npm install -D firebase-tools
npx firebase init emulators # marcar Firestore
npx firebase emulators:start --only firestore --project demo-boutiqueUn identificador de proyecto que empieza por demo- le indica al emulador que funcione sin cuenta ni facturación.
En la aplicación, conecta el SDK al emulador solo en desarrollo:
import { connectFirestoreEmulator, getFirestore } from 'firebase/firestore'
export const db = getFirestore(firebaseApp)
if (import.meta.env.DEV) {
connectFirestoreEmulator(db, '127.0.0.1', 8080)
}Desde firebase-tools 15, una versión del JDK anterior a esa hace fallar el arranque con el mensaje «firebase-tools no longer supports Java version before 21». Compruébalo con java -version.
Las reglas de seguridad
Sin reglas, la base está cerrada o abierta a todo el mundo. El modo «prueba» que se propone al crearla caduca a los treinta días, no lo dejes en producción.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /avis/{avisId} {
// lectura pública
allow read: if true;
// escritura reservada a quien haya iniciado sesión, y solo sobre su propia reseña
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;
}
}
}Las reglas también se escriben y se prueban contra el emulador, lo que evita descubrir un agujero en producción.
Lo que ha cambiado desde el SDK 8
Muchos ejemplos que siguen circulando usan la antigua API con espacios de nombres. Ya no funciona tal cual desde Firebase 9:
// SDK antiguo (8 y anteriores) — ya no funciona
import firebase from 'firebase'
const db = firebase.initializeApp(config).database()
db.ref('avis').push({ nom: 'Damien' })
// SDK modular (9 y posteriores)
import { initializeApp } from 'firebase/app'
import { addDoc, collection, getFirestore } from 'firebase/firestore'
const db = getFirestore(initializeApp(config))
await addDoc(collection(db, 'avis'), { nom: 'Damien' })El troceado en funciones importadas no es cosmético: permite que el bundler conserve solo lo que usas. En una aplicación que únicamente lee de Firestore, la diferencia de peso se nota.
Del lado de VueFire, la antigua opción firebase: { … } en los componentes y el objeto $firebaseRefs han desaparecido: todo pasa por useCollection y useDocument.
Para ir más lejos
Este montaje da por sabidos los componentes y la reactividad de Vue. Si no es tu caso, empieza por el tutorial de Vue 3 para principiantes. Para compartir los datos de Firebase entre componentes alejados, un store de Pinia que encapsule las llamadas a Firestore es un buen patrón.
Errores frecuentes
firebase.initializeApp(config).database() y el objeto global firebase ya no funcionan desde la versión 9. Todo pasa por funciones importadas.firebase: { … } en los componentes y $firebaseRefs han desaparecido: usa useCollection y useDocument.

