DEV Community

Cover image for Comment Utiliser l'API Firebase: Guide d'Intégration Complet (2026)
Antoine Laurent
Antoine Laurent

Posted on • Originally published at apidog.com

Comment Utiliser l'API Firebase: Guide d'Intégration Complet (2026)

Vous développez une application. Les utilisateurs doivent se connecter. Les données doivent se synchroniser en temps réel. Les fichiers nécessitent un stockage. Vous pourriez déployer des serveurs, configurer des bases de données et gérer l'infrastructure pendant des semaines. Ou vous pourriez utiliser Firebase.

Essayez Apidog dès aujourd'hui

Firebase alimente plus de 1,5 million d'applications, dont The New York Times, Duolingo et Alibaba. Les développeurs le choisissent car il élimine la complexité du backend. Vous vous concentrez sur les fonctionnalités, pas sur la maintenance des serveurs. Mais l'API Firebase a ses particularités. Les flux d'authentification déroutent les débutants. Les règles de base de données piègent les développeurs expérimentés. Les fonctions Cloud semblent magiques jusqu'à ce que vous compreniez les déclencheurs.

J'ai intégré Firebase dans des applications de production servant des millions d'utilisateurs. J'ai commis toutes les erreurs possibles : exposé des clés de compte de service, écrit des requêtes inefficaces, déployé des fonctions défectueuses. Ce guide condense ces leçons.

Vous apprendrez l'authentification, les opérations de base de données, les fonctions Cloud et le stockage. Vous verrez du code fonctionnel, pas seulement de la théorie. Vous éviterez les pièges qui causent des problèmes en production.

💡Tester les API Firebase devient plus facile avec des outils clients API appropriés. Apidog vous permet d'organiser les points d'accès, de tester les flux d'authentification et de partager des collections avec votre équipe. Nous vous montrerons où il s'intègre naturellement dans le flux de travail.

Qu'est-ce que l'API Firebase et pourquoi est-elle importante ?

Firebase n'est pas une seule API. C'est une suite de services backend accessibles via des SDK unifiés et des points d'accès REST.

Services Firebase principaux

Service Objectif Type d'API
Authentification Connexion et identité de l'utilisateur SDK + REST
Base de données Firestore Base de données de documents NoSQL SDK + REST
Base de données en temps réel Synchronisation JSON en temps réel SDK + REST
Cloud Storage Stockage de fichiers et CDN SDK + REST
Cloud Functions Calcul sans serveur CLI de déploiement
Hébergement Hébergement web statique CLI de déploiement
Cloud Messaging Notifications push API HTTP v1

Quand Firebase est pertinent

Firebase résout bien des problèmes spécifiques :

Utilisez Firebase lorsque :

  • Vous avez besoin d'une synchronisation en temps réel (chat, collaboration, mises à jour en direct)
  • Vous souhaitez une architecture sans serveur (pas de gestion d'infrastructure)
  • Vous développez des applications mobiles ou web (les SDK gèrent les différences de plateforme)
  • Vous avez besoin d'un support hors ligne (les SDK mettent automatiquement les données en cache)
  • Vous souhaitez une authentification intégrée (Google, Apple, e-mail, connexion téléphonique)

Évitez Firebase lorsque :

  • Vous avez besoin de requêtes relationnelles complexes (utilisez plutôt PostgreSQL)
  • Vous avez des exigences strictes en matière de résidence des données (les régions Firebase sont limitées)
  • Vous avez besoin de toutes les capacités SQL (des limitations de requêtes Firestore existent)
  • Le coût à grande échelle est plus important que la vitesse de développement (l'auto-hébergement est moins cher)

L'architecture de l'API Firebase

Firebase utilise une approche hybride :

┌─────────────────────────────────────────────────────────┐
│                    Votre application                     │
├─────────────────────────────────────────────────────────┤
│  SDK Firebase (Client)                                  │
│  - Gère automatiquement les jetons d'authentification   │
│  - Gère le cache hors ligne                              │
│  - Écouteurs en temps réel                               │
└─────────────────────────────────────────────────────────┘
                          │
                          │ HTTPS + WebSocket
                          ▼
┌─────────────────────────────────────────────────────────┐
│                   Backend Firebase                       │
├──────────────┬──────────────┬──────────────┬────────────┤
│   Service    │  Base de     │   Service    │ Runtime    │
│   d'Auth.    │  données     │   de Stock.  │  des Fcts  │
│              │  Firestore   │              │            │
└──────────────┴──────────────┴──────────────┴────────────┘
Enter fullscreen mode Exit fullscreen mode

Les SDK clients abstraient la couche HTTP. En arrière-plan, chaque opération se traduit par des appels d'API REST avec authentification JWT.

Authentification Firebase : Configuration complète

L'authentification est votre première intégration Firebase. Si cela échoue, tout le reste échoue.

Étape 1 : Créer un projet Firebase

  1. Allez à la Console Firebase

Capture d'écran de la console Firebase montrant le bouton « Ajouter un projet »

Cliquez sur "Ajouter un projet" et saisissez le nom du projet (pas d'espaces)

Capture d'écran de l'étape de saisie du nom du projet dans la console Firebase

Activez Google Analytics (facultatif mais recommandé)

Capture d'écran de l'étape d'activation de Google Analytics pour un projet Firebase

Cliquez sur "Créer le projet"

Capture d'écran de l'étape finale de création d'un projet Firebase

Attendez 30 secondes pour le provisionnement. Vous verrez le tableau de bord du projet.

Étape 2 : Enregistrer votre application

Pour les applications web :

// Dans la console Firebase > Paramètres du projet > Général
// Cliquez sur "Ajouter une application" > icône Web

// Enregistrer l'application web
const firebaseConfig = {
  apiKey: "AIzaSyDxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  authDomain: "your-app.firebaseapp.com",
  projectId: "your-app",
  storageBucket: "your-app.appspot.com",
  messagingSenderId: "123456789012",
  appId: "1:123456789012:web:abc123def456"
};

// Initialiser Firebase
import { initializeApp } from 'firebase/app';
const app = initializeApp(firebaseConfig);
Enter fullscreen mode Exit fullscreen mode

Pour les applications iOS :

Téléchargez GoogleService-Info.plist et ajoutez-le au projet Xcode. Assurez-vous que "Target Membership" inclut votre application.

Pour les applications Android :

Téléchargez google-services.json et placez-le dans le répertoire app/. Ajoutez à build.gradle :

// build.gradle au niveau du projet
buildscript {
    dependencies {
        classpath 'com.google.gms:google-services:4.4.0'
    }
}

// build.gradle au niveau de l'application
plugins {
    id 'com.google.gms.google-services'
}
Enter fullscreen mode Exit fullscreen mode

Étape 3 : Activer les méthodes d'authentification

Dans la console Firebase > Authentification > Méthode de connexion :

  1. E-mail/Mot de passe : Activez pour une inscription traditionnelle
  2. Google : Ajoutez votre empreinte de certificat SHA-1 (Android) ou l'ID de bundle (iOS)
  3. Apple : Obligatoire pour les applications iOS si vous activez une connexion sociale
  4. Téléphone : Activez pour l'authentification par SMS (nécessite une facturation)

Étape 4 : Implémenter le flux d'authentification

Inscription par e-mail/mot de passe :

import {
  createUserWithEmailAndPassword,
  getAuth,
  updateProfile
} from 'firebase/auth';

const auth = getAuth(app);

async function signUp(email, password, displayName) {
  try {
    const userCredential = await createUserWithEmailAndPassword(
      auth,
      email,
      password
    );

    // Définir le nom d'affichage
    await updateProfile(userCredential.user, {
      displayName: displayName
    });

    console.log('Utilisateur créé :', userCredential.user.uid);
    return userCredential.user;
  } catch (error) {
    // Gérer les codes d'erreur spécifiques
    switch (error.code) {
      case 'auth/email-already-in-use':
        throw new Error('Cet e-mail est déjà enregistré');
      case 'auth/weak-password':
        throw new Error('Le mot de passe doit contenir au moins 6 caractères');
      case 'auth/invalid-email':
        throw new Error('Adresse e-mail invalide');
      default:
        throw new Error("L'inscription a échoué : " + error.message);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Connexion par e-mail/mot de passe :

import {
  signInWithEmailAndPassword,
  signOut
} from 'firebase/auth';

async function signIn(email, password) {
  try {
    const userCredential = await signInWithEmailAndPassword(
      auth,
      email,
      password
    );

    const user = userCredential.user;

    // Obtenir le jeton d'identification pour les appels API
    const idToken = await user.getIdToken();
    console.log('Jeton d\'authentification :', idToken);

    return user;
  } catch (error) {
    switch (error.code) {
      case 'auth/user-not-found':
        throw new Error('Aucun compte avec cet e-mail');
      case 'auth/wrong-password':
        throw new Error('Mot de passe incorrect');
      case 'auth/too-many-requests':
        throw new Error('Trop de tentatives. Réessayez plus tard');
      default:
        throw new Error('La connexion a échoué');
    }
  }
}

async function logOut() {
  await signOut(auth);
  console.log('Utilisateur déconnecté');
}
Enter fullscreen mode Exit fullscreen mode

Connexion Google (Web) :

import {
  GoogleAuthProvider,
  signInWithPopup
} from 'firebase/auth';

async function signInWithGoogle() {
  const provider = new GoogleAuthProvider();

  // Demander des étendues supplémentaires
  provider.addScope('email');
  provider.addScope('profile');

  try {
    const result = await signInWithPopup(auth, provider);
    const user = result.user;

    // Accéder au jeton OAuth Google
    const credential = GoogleAuthProvider.credentialFromResult(result);
    const googleAccessToken = credential.accessToken;

    return user;
  } catch (error) {
    if (error.code === 'auth/popup-closed-by-user') {
      throw new Error("Connexion annulée");
    }
    throw new Error('La connexion Google a échoué');
  }
}
Enter fullscreen mode Exit fullscreen mode

Étape 5 : Protéger les routes avec l'état d'authentification

import { onAuthStateChanged } from 'firebase/auth';

// S'abonner aux changements d'état d'authentification
onAuthStateChanged(auth, (user) => {
  if (user) {
    // L'utilisateur est connecté
    console.log('Utilisateur :', user.email);
    // Rediriger vers le tableau de bord
    window.location.href = '/dashboard';
  } else {
    // L'utilisateur est déconnecté
    console.log('Aucun utilisateur');
    // Rediriger vers la page de connexion
    window.location.href = '/login';
  }
});
Enter fullscreen mode Exit fullscreen mode

Erreurs d'authentification courantes

Erreur 1 : Ne pas gérer le rafraîchissement des jetons

Le SDK Firebase rafraîchit automatiquement les jetons. Mais si vous mettez en cache les jetons côté serveur, ils expirent après 1 heure. Vérifiez toujours les jetons à chaque requête ou implémentez une logique de rafraîchissement.

Erreur 2 : Exposer les identifiants d'administrateur dans le code client

N'utilisez jamais les clés de compte de service dans les applications clientes. Les comptes de service contournent les règles de sécurité. Utilisez-les uniquement dans des environnements serveur de confiance.

Erreur 3 : Oublier la vérification de l'e-mail

import { sendEmailVerification } from 'firebase/auth';

async function sendVerificationEmail(user) {
  await sendEmailVerification(user);
  console.log('E-mail de vérification envoyé');
}

// Vérifier l'état de la vérification
if (!auth.currentUser.emailVerified) {
  console.log('E-mail non vérifié');
  // Restreindre l'accès
}
Enter fullscreen mode Exit fullscreen mode

Base de données Firestore : Opérations et requêtes

Firestore est la base de données NoSQL de Firebase. Les documents sont organisés en collections. Les requêtes s'adaptent automatiquement.

Structure des données

votre-projet (racine)
└── utilisateurs (collection)
    ├── userId123 (document)
    │   ├── nom: "Jean"
    │   ├── email: "jean@example.com"
    │   └── publications (sous-collection)
    │       ├── postId1 (document)
    │       └── postId2 (document)
    └── userId456 (document)
Enter fullscreen mode Exit fullscreen mode

Initialiser Firestore

import { getFirestore } from 'firebase/firestore';

const db = getFirestore(app);
Enter fullscreen mode Exit fullscreen mode

Créer des documents

import {
  collection,
  addDoc,
  setDoc,
  doc
} from 'firebase/firestore';

// Option 1 : ID auto-généré
async function createUser(userData) {
  const docRef = await addDoc(collection(db, 'users'), userData);
  console.log('Document écrit avec l\'ID :', docRef.id);
  return docRef.id;
}

// Option 2 : ID personnalisé
async function createUserWithId(userId, userData) {
  await setDoc(doc(db, 'users', userId), userData);
  console.log('Document écrit avec l\'ID personnalisé :', userId);
}

// Utilisation
const userId = await createUser({
  name: 'Alice',
  email: 'alice@example.com',
  createdAt: new Date(),
  role: 'user'
});
Enter fullscreen mode Exit fullscreen mode

Lire des documents

import {
  getDoc,
  getDocs,
  query,
  where,
  orderBy,
  limit
} from 'firebase/firestore';

// Obtenir un seul document
async function getUser(userId) {
  const docRef = doc(db, 'users', userId);
  const docSnap = await getDoc(docRef);

  if (docSnap.exists()) {
    return docSnap.data();
  } else {
    throw new Error('Utilisateur non trouvé');
  }
}

// Requête avec filtres
async function getUsersByRole(role) {
  const q = query(
    collection(db, 'users'),
    where('role', '==', role),
    orderBy('createdAt', 'desc'),
    limit(10)
  );

  const querySnapshot = await getDocs(q);
  const users = [];

  querySnapshot.forEach((doc) => {
    users.push({ id: doc.id, ...doc.data() });
  });

  return users;
}

// Utilisation
const adminUsers = await getUsersByRole('admin');
console.log('Utilisateurs administrateurs :', adminUsers);
Enter fullscreen mode Exit fullscreen mode

Mettre à jour des documents

import {
  updateDoc,
  increment,
  arrayUnion,
  arrayRemove
} from 'firebase/firestore';

async function updateUser(userId, updates) {
  const userRef = doc(db, 'users', userId);
  await updateDoc(userRef, updates);
}

// Opérations atomiques
await updateUser('userId123', {
  loginCount: increment(1),
  tags: arrayUnion('premium', 'beta-tester'),
  lastLogin: new Date()
});

// Supprimer d'un tableau
await updateUser('userId123', {
  tags: arrayRemove('beta-tester')
});
Enter fullscreen mode Exit fullscreen mode

Supprimer des documents

import { deleteDoc } from 'firebase/firestore';

async function deleteUser(userId) {
  await deleteDoc(doc(db, 'users', userId));
  console.log('Utilisateur supprimé');
}
Enter fullscreen mode Exit fullscreen mode

Écouteurs en temps réel

import { onSnapshot } from 'firebase/firestore';

// Écouter un seul document
const unsubscribe = onSnapshot(
  doc(db, 'users', userId),
  (doc) => {
    console.log('Utilisateur mis à jour :', doc.data());
  },
  (error) => {
    console.error('Erreur d\'écoute :', error);
  }
);

// Écouter les résultats d'une requête
const q = query(collection(db, 'posts'), where('published', '==', true));

const unsubscribeQuery = onSnapshot(q, (snapshot) => {
  const posts = snapshot.docs.map(doc => ({
    id: doc.id,
    ...doc.data()
  }));
  console.log('Publications publiées :', posts);
});

// Arrêter d'écouter
unsubscribe();
unsubscribeQuery();
Enter fullscreen mode Exit fullscreen mode

Règles de sécurité Firestore

Sans règles appropriées, n'importe qui peut lire vos données. Définissez les règles dans la console Firebase > Firestore > Règles :

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

    // Fonction d'aide
    function isAuthenticated() {
      return request.auth != null;
    }

    function isOwner(userId) {
      return request.auth.uid == userId;
    }

    // Collection des utilisateurs
    match /users/{userId} {
      allow read: if isAuthenticated();
      allow create: if isAuthenticated() && isOwner(userId);
      allow update, delete: if isOwner(userId);
    }

    // Collection des publications
    match /posts/{postId} {
      allow read: if true; // Lecture publique
      allow create: if isAuthenticated();
      allow update, delete: if resource.data.authorId == request.auth.uid;
    }

    // Sous-collection privée
    match /users/{userId}/private/{document} {
      allow read, write: if isOwner(userId);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Limitations des requêtes

Firestore a des contraintes :

  • Pas de requêtes OU (utilisez in avec un tableau ou plusieurs requêtes)
  • Pas de recherches par caractères génériques (utilisez Algolia ou Meilisearch pour le texte intégral)
  • Les requêtes composées nécessitent des index (Firestore crée automatiquement un index sur un seul champ)
  • Limite de 30 disjonctions dans les requêtes in

Solution de contournement pour les requêtes OU :

// Au lieu de : where('status', '==', 'active') OU where('status', '==', 'pending')

const activeQuery = query(
  collection(db, 'tasks'),
  where('status', '==', 'active')
);

const pendingQuery = query(
  collection(db, 'tasks'),
  where('status', '==', 'pending')
);

const [activeSnap, pendingSnap] = await Promise.all([
  getDocs(activeQuery),
  getDocs(pendingQuery)
]);

// Fusionner les résultats côté client
Enter fullscreen mode Exit fullscreen mode

Cloud Functions : Logique backend sans serveur

Les fonctions Cloud exécutent du code backend sans gérer de serveurs. Elles se déclenchent lors de modifications de base de données, de requêtes HTTP ou d'événements planifiés.

Configuration

# Installer Firebase CLI
npm install -g firebase-tools

# Connexion
firebase login

# Initialiser les fonctions dans votre projet
firebase init functions

# Sélectionner : JavaScript, ESLint oui, Express.js non
Enter fullscreen mode Exit fullscreen mode

Fonctions HTTP (points d'accès API)

// functions/index.js
const { onRequest } = require('firebase-functions/v2/https');
const admin = require('firebase-admin');

admin.initializeApp();
const db = admin.firestore();

// Point d'accès public
exports.getPublicData = onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  try {
    const snapshot = await db.collection('public').get();
    const data = snapshot.docs.map(doc => doc.data());
    res.json({ success: true, data });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Point d'accès protégé (vérifier le jeton d'authentification)
exports.getUserProfile = onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  // Obtenir le jeton de l'en-tête Authorization
  const authHeader = req.headers.authorization || '';
  const token = authHeader.split('Bearer ')[1];

  if (!token) {
    return res.status(401).json({ error: 'Non autorisé' });
  }

  try {
    // Vérifier le jeton
    const decodedToken = await admin.auth().verifyIdToken(token);
    const userId = decodedToken.uid;

    // Obtenir les données de l'utilisateur
    const userDoc = await db.collection('users').doc(userId).get();

    if (!userDoc.exists) {
      return res.status(404).json({ error: 'Utilisateur non trouvé' });
    }

    res.json({
      success: true,
      data: { id: userId, ...userDoc.data() }
    });
  } catch (error) {
    res.status(401).json({ error: 'Jeton invalide' });
  }
});
Enter fullscreen mode Exit fullscreen mode

Déploiement :

firebase deploy --only functions:getUserProfile
Enter fullscreen mode Exit fullscreen mode

Appel depuis le client :

async function getUserProfile(token) {
  const response = await fetch(
    'https://us-central1-your-app.cloudfunctions.net/getUserProfile',
    {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }
  );

  const data = await response.json();
  return data;
}
Enter fullscreen mode Exit fullscreen mode

Déclencheurs de base de données

const { onDocumentWritten } = require('firebase-functions/v2/firestore');

// Déclencher lorsque le document utilisateur change
exports.onUserUpdate = onDocumentWritten(
  'users/{userId}',
  async (event) => {
    const userId = event.params.userId;
    const before = event.data?.before?.data();
    const after = event.data?.after?.data();

    // Vérifier si l'e-mail a changé
    if (before?.email !== after?.email) {
      console.log(`L'e-mail de l'utilisateur ${userId} a changé : ${before?.email}${after?.email}`);

      // Envoyer un e-mail de notification
      await admin.auth().getUser(userId);
      // Ajouter votre logique d'e-mail ici
    }
  }
);

// Déclencher lors de la création d'une nouvelle publication
exports.onNewPost = onDocumentWritten(
  'posts/{postId}',
  async (event) => {
    const post = event.data?.after?.data();

    if (!post) return; // Document supprimé

    // Vérifier s'il s'agit d'un nouveau document
    if (!event.data?.before?.exists) {
      console.log('Nouvelle publication créée :', post.title);

      // Notifier les abonnés
      const followersSnap = await admin.firestore()
        .collection('users')
        .where('following', 'array-contains', post.authorId)
        .get();

      const notifications = followersSnap.docs.map(doc => ({
        userId: doc.id,
        postId: event.params.postId,
        type: 'new_post',
        createdAt: admin.firestore.FieldValue.serverTimestamp()
      }));

      const batch = admin.firestore().batch();
      notifications.forEach(notif => {
        const ref = admin.firestore().collection('notifications').doc();
        batch.set(ref, notif);
      });

      await batch.commit();
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

Fonctions planifiées (tâches Cron)

const { onSchedule } = require('firebase-functions/v2/scheduler');

// Exécuter tous les jours à minuit UTC
exports.dailyCleanup = onSchedule('toutes les 24 heures', async (event) => {
  console.log('Exécution du nettoyage quotidien');

  // Supprimer les anciennes notifications (plus de 30 jours)
  const thirtyDaysAgo = new Date();
  thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

  const oldNotifs = await admin.firestore()
    .collection('notifications')
    .where('createdAt', '<', thirtyDaysAgo)
    .get();

  const batch = admin.firestore().batch();
  oldNotifs.forEach(doc => batch.delete(doc.ref));
  await batch.commit();

  console.log(`Supprimé ${oldNotifs.size} anciennes notifications`);
});
Enter fullscreen mode Exit fullscreen mode

Configuration de l'environnement

# Définir les variables d'environnement
firebase functions:config:set \
  stripe.secret="sk_test_xxx" \
  email.api_key="key_xxx"

# Accéder aux fonctions
const config = require('firebase-functions/config');
const stripe = require('stripe')(config.stripe.secret);
Enter fullscreen mode Exit fullscreen mode

Cloud Storage : Téléchargement et gestion de fichiers

Stockez les téléchargements d'utilisateurs, les images et les fichiers avec une distribution CDN automatique.

Configuration des règles de stockage

// Console Firebase > Stockage > Règles
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // Dossier des téléchargements d'utilisateurs
    match /users/{userId}/{allPaths=**} {
      allow read: if true; // Lecture publique
      allow write: if request.auth.uid == userId;
      allow delete: if request.auth.uid == userId;
    }

    // Actifs publics
    match /public/{allPaths=**} {
      allow read: if true;
      allow write: if false; // Administrateur uniquement via la console Firebase
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Télécharger des fichiers (Client)

import {
  getStorage,
  ref,
  uploadBytesResumable,
  getDownloadURL
} from 'firebase/storage';

const storage = getStorage(app);

async function uploadProfileImage(userId, file) {
  // Créer une référence de stockage
  const storageRef = ref(storage, `users/${userId}/profile/${file.name}`);

  // Télécharger le fichier
  const uploadTask = uploadBytesResumable(storageRef, file);

  return new Promise((resolve, reject) => {
    uploadTask.on(
      'state_changed',
      (snapshot) => {
        // Suivre la progression
        const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log(`Téléchargement : ${progress.toFixed(0)}%`);
      },
      (error) => {
        // Gérer les erreurs
        switch (error.code) {
          case 'storage/unauthorized':
            reject(new Error('Vous n\'avez pas la permission'));
            break;
          case 'storage/canceled':
            reject(new Error('Téléchargement annulé'));
            break;
          default:
            reject(new Error('Le téléchargement a échoué'));
        }
      },
      async () => {
        // Téléchargement terminé
        const downloadURL = await getDownloadURL(uploadTask.snapshot.ref);
        console.log('Fichier disponible à :', downloadURL);
        resolve(downloadURL);
      }
    );
  });
}

// Utilisation
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];

if (file) {
  const imageUrl = await uploadProfileImage(auth.currentUser.uid, file);

  // Enregistrer l'URL dans Firestore
  await updateDoc(doc(db, 'users', auth.currentUser.uid), {
    profileImage: imageUrl
  });
}
Enter fullscreen mode Exit fullscreen mode

Télécharger des fichiers

import { getDownloadURL } from 'firebase/storage';

async function getProfileImage(userId) {
  const imageRef = ref(storage, `users/${userId}/profile/avatar.png`);

  try {
    const url = await getDownloadURL(imageRef);
    return url;
  } catch (error) {
    if (error.code === 'storage/object-not-found') {
      return null; // Pas d'image de profil
    }
    throw error;
  }
}
Enter fullscreen mode Exit fullscreen mode

Supprimer des fichiers

import { deleteObject } from 'firebase/storage';

async function deleteProfileImage(userId) {
  const imageRef = ref(storage, `users/${userId}/profile/avatar.png`);
  await deleteObject(imageRef);
  console.log('Image de profil supprimée');
}
Enter fullscreen mode Exit fullscreen mode

Tester les API Firebase avec Apidog

Firebase fournit des API REST pour tous les services. Les tester directement aide à déboguer les problèmes et à comprendre les requêtes sous-jacentes.

Importer l'API REST Firebase

  1. Ouvrez Apidog
  2. Créez un nouveau projet : "Firebase API"
  3. Importez la spécification OpenAPI de la documentation Firebase
  4. Ou ajoutez manuellement des points d'accès :

Point d'accès REST Firestore :

POST https://firestore.googleapis.com/v1/projects/{projectId}/databases/(default)/documents
Authorization: Bearer {oauth2_token}
Content-Type: application/json

{
  "fields": {
    "name": { "stringValue": "John" },
    "email": { "stringValue": "john@example.com" },
    "age": { "integerValue": 30 }
  }
}
Enter fullscreen mode Exit fullscreen mode

Point d'accès d'authentification :

POST https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={api_key}
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "secret123",
  "returnSecureToken": true
}
Enter fullscreen mode Exit fullscreen mode

Tester le flux d'authentification

  1. Créer une requête : "Connexion"
  2. Définir la méthode : POST
  3. Ajouter l'e-mail/mot de passe dans le corps
  4. Enregistrer le jeton de réponse comme variable d'environnement
  5. Utiliser {{token}} dans les requêtes ultérieures

Déboguer les règles de sécurité

Utilisez la suite d'émulateurs Firebase pour les tests locaux :

# Démarrer l'émulateur
firebase emulators:start

# Tester contre Firestore local
# http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Bonnes pratiques de production

1. Implémenter une gestion d'erreurs appropriée

// Logique de réessai pour les échecs transitoires
async function firestoreWithRetry(operation, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await operation();
    } catch (error) {
      if (
        error.code === 'unavailable' ||
        error.code === 'deadline-exceeded'
      ) {
        const delay = Math.pow(2, i) * 1000; // Recul exponentiel
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      throw error;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

2. Optimiser les performances des requêtes

Ajoutez des index composites pour les requêtes multi-champs :

// Cette requête nécessite un index composite
const q = query(
  collection(db, 'posts'),
  where('category', '==', 'tech'),
  where('views', '>', 1000),
  orderBy('views', 'desc')
);
Enter fullscreen mode Exit fullscreen mode

Firestore vous invite à créer l'index avec un lien direct lorsque vous exécutez cette requête.

3. Opérations par lots

import { writeBatch } from 'firebase/firestore';

async function bulkUpdate(userIds, updates) {
  const batch = writeBatch(db);

  userIds.forEach(id => {
    const ref = doc(db, 'users', id);
    batch.update(ref, updates);
  });

  await batch.commit();
  console.log(`Mis à jour ${userIds.length} utilisateurs`);
}

// Maximum 500 opérations par lot
Enter fullscreen mode Exit fullscreen mode

4. Surveiller les coûts

Tarification Firebase :

Service Tier gratuit Payant
Firestore 50K lectures/jour 0,036 $/100K lectures
Stockage 5 Go 0,023 $/Go
Fonctions 2M invocations 0,40 $/1M
Authentification 10K/mois 0,0055 $/100K

Définissez des alertes budgétaires dans la console Google Cloud.

5. Sécuriser les comptes de service

// FAUX : Ne jamais faire cela dans le code client
admin.initializeApp({
  credential: admin.credential.cert(require('./serviceAccountKey.json'))
});

// CORRECT : Utiliser uniquement dans un environnement serveur
const serviceAccount = JSON.parse(process.env.FIREBASE_SERVICE_ACCOUNT);
admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});
Enter fullscreen mode Exit fullscreen mode

6. Gérer les scénarios hors ligne

// Activer la persistance hors ligne (web)
import { enableMultiTabIndexedDbPersistence } from 'firebase/firestore';

enableMultiTabIndexedDbPersistence(db)
  .catch((err) => {
    if (err.code === 'failed-precondition') {
      // Plusieurs onglets ouverts
    } else if (err.code === 'unimplemented') {
      // Le navigateur ne prend pas en charge
    }
  });

// Écouter la connectivité
import { onSnapshot } from 'firebase/firestore';

onSnapshot(doc(db, 'status', 'online'), (doc) => {
  if (!doc.exists()) {
    console.log('Vous êtes hors ligne');
    // Afficher l'interface utilisateur hors ligne
  }
});
Enter fullscreen mode Exit fullscreen mode

Problèmes et solutions courants de l'API Firebase

Problème 1 : Erreurs d'autorisation refusée

Symptôme : Erreur : 7 PERMISSION_DENIED

Cause : Les règles de sécurité bloquent l'opération

Correction :

  1. Vérifiez les règles dans la console Firebase
  2. Vérifiez que request.auth.uid correspond à l'utilisateur attendu
  3. Testez les règles avec le Playground de règles

Problème 2 : Expiration du jeton

Symptôme : Erreur : Jeton d'ID expiré

Correction :

// Forcer le rafraîchissement du jeton
const user = auth.currentUser;
if (user) {
  await user.getIdToken(true); // Forcer le rafraîchissement
}
Enter fullscreen mode Exit fullscreen mode

Problème 3 : Latence de démarrage à froid

Symptôme : Les fonctions Cloud prennent 2 à 5 secondes lors du premier appel

Correction :

// Garder les fonctions "chaudes" avec des pings planifiés
exports.keepWarm = onSchedule('toutes les 60 secondes', async () => {
  await fetch('https://votre-fonction.cloudfunctions.net/health');
});
Enter fullscreen mode Exit fullscreen mode

Problème 4 : La requête renvoie des résultats vides

Symptôme : La requête devrait renvoyer des données mais renvoie un tableau vide

Cause : Index manquant ou ordre des champs incorrect

Correction : Vérifiez la console Firestore > Index pour les index composites requis.

Cas d'utilisation réels

Application Fintech : Mises à jour de transactions en temps réel

Une startup de paiement a utilisé Firebase Firestore pour créer des notifications de transactions en temps réel. Lorsqu'un paiement est traité, les fonctions Cloud déclenchent des mises à jour sur tous les tableaux de bord d'administration connectés en moins de 200 ms. Résultat : une réduction de 40 % des tickets de support concernant les transactions "en attente".

E-commerce : Synchronisation des stocks

Un détaillant en ligne synchronise son inventaire sur le web, iOS et Android à l'aide des écouteurs Firestore. Lorsque le stock change, tous les clients sont mis à jour automatiquement. La persistance hors ligne garantit que les employés de l'entrepôt peuvent scanner des articles sans connectivité, avec une synchronisation automatique une fois reconnectés.

SaaS : Authentification multi-locataires

Une plateforme B2B utilise Firebase Auth avec des revendications personnalisées pour l'accès basé sur les rôles. Les utilisateurs administrateurs obtiennent des autorisations élevées via des fonctions Cloud qui valident les configurations de locataires Firestore. Une seule base de code sert plus de 500 organisations avec des données isolées.

Conclusion

L'intégration de l'API Firebase implique quatre services principaux :

  • Authentification : Connexion par e-mail, Google, Apple avec des jetons JWT
  • Firestore : Base de données NoSQL avec des écouteurs en temps réel et des règles de sécurité
  • Cloud Functions : Backend sans serveur déclenché par des événements ou HTTP
  • Stockage : Téléchargement de fichiers avec distribution CDN

Vous avez appris les flux d'authentification, les opérations de base de données, le déploiement de fonctions et la gestion de fichiers. Vous avez vu des modèles de production : gestion des erreurs, traitement par lots, support hors ligne et sécurité.

FAQ

Firebase est-il gratuit ?

Oui, Firebase propose un niveau gratuit généreux (plan Spark) incluant 5 Go de stockage, 50K lectures Firestore/jour, 2M invocations de fonctions Cloud et 10K utilisateurs Auth/mois. Les plans payants (Blaze) utilisent une tarification à l'usage.

Puis-je utiliser Firebase avec des bases de données existantes ?

Oui. Utilisez les extensions Firebase pour synchroniser avec PostgreSQL, MySQL ou MongoDB. Ou appelez des API externes depuis les fonctions Cloud pour vous intégrer à des systèmes existants.

Comment migrer de Firebase vers une autre plateforme ?

Exportez les données à l'aide des fonctions d'exportation Firestore ou de la CLI Firebase. Pour les grands ensembles de données, utilisez le pipeline d'exportation Dataflow. La complexité de la migration dépend de la structure de vos données.

Firebase prend-il en charge GraphQL ?

Pas nativement. Utilisez des solutions tierces comme firestore-graphql ou construisez une couche GraphQL avec Cloud Functions et Apollo Server.

Puis-je utiliser Firebase sur site ?

Non. Firebase est exclusivement sur Google Cloud. Pour des alternatives auto-hébergées, envisagez Appwrite, Supabase ou Nhost.

Comment gérer les téléchargements de fichiers de plus de 100 Mo ?

Utilisez les téléchargements reprenables avec découpage (chunking). Le SDK Firebase gère cela automatiquement. Pour les fichiers très volumineux, utilisez directement Google Cloud Storage avec des URL signées.

Que se passe-t-il si je dépasse les limites de requêtes Firestore ?

Les requêtes échouent avec l'erreur FAILED_PRECONDITION. Ajoutez les index requis ou restructurez les requêtes. Firestore fournit des liens directs pour créer les index manquants dans le message d'erreur.

Firebase est-il conforme au RGPD ?

Oui, Firebase offre un traitement des données conforme au RGPD. Activez la résidence des données dans des régions spécifiques, implémentez l'exportation/suppression des données utilisateur et signez l'avenant relatif au traitement des données de Google.

Top comments (0)