Von der API mit Namespace zur modularen Anwendung wechseln

Apps, die eine Firebase Web API mit Namespace verwenden, von den compat-Bibliotheken bis hin zu Version 8 oder früher, sollten gemäß der Anleitung in diesem Leitfaden zur modularen API migrieren.

In diesem Leitfaden wird davon ausgegangen, dass Sie mit der API mit Namensraum vertraut sind und einen Module Bundler wie Webpack oder Rollup für das Upgrade und die laufende modulare App-Entwicklung verwenden.

Die Verwendung eines Modul-Bundlers in Ihrer Entwicklungsumgebung wird dringend empfohlen. Wenn Sie keinen verwenden, können Sie die Hauptvorteile der modularen API in Bezug auf die reduzierte App-Größe nicht nutzen. Sie benötigen npm oder yarn, um das SDK zu installieren.

Die Upgradeschritte in diesem Leitfaden basieren auf einer fiktiven Web-App, die die SDKs Authentication und Cloud Firestore verwendet. Anhand der Beispiele können Sie die Konzepte und praktischen Schritte nachvollziehen, die für ein Upgrade aller unterstützten Firebase Web SDKs erforderlich sind.

Informationen zu den Bibliotheken mit Namespace (compat)

Für das Firebase Web SDK sind zwei Arten von Bibliotheken verfügbar:

  • Modular: Eine neue API-Oberfläche, die das Tree-Shaking (Entfernen von nicht verwendetem Code) erleichtert, damit Ihre Webanwendung so klein und schnell wie möglich ist.
  • Namespaced (compat): Eine vertraute API-Oberfläche, die vollständig mit den früheren Versionen des SDK kompatibel ist. So können Sie ein Upgrade durchführen, ohne den gesamten Firebase-Code auf einmal ändern zu müssen. Kompatibilitätsbibliotheken haben kaum oder gar keine Vorteile in Bezug auf Größe oder Leistung gegenüber ihren Gegenstücken mit Namespace.

In diesem Leitfaden wird davon ausgegangen, dass Sie die Kompatibilitätsbibliotheken nutzen, um das Upgrade zu vereinfachen. Mit diesen Bibliotheken können Sie weiterhin Namespace-Code zusammen mit Code verwenden, der für die modulare API refaktoriert wurde. So können Sie Ihre App während des Upgrades einfacher kompilieren und debuggen.

Bei Apps, die nur sehr wenig mit dem Firebase Web SDK interagieren, z. B. eine App, die nur einen einfachen Aufruf an die Authentication APIs sendet, kann es sinnvoll sein, älteren Namespace-Code ohne die Kompatibilitätsbibliotheken zu refaktorieren. Wenn Sie ein Upgrade einer solchen App durchführen, können Sie der Anleitung in diesem Leitfaden für die modulare API folgen, ohne die Kompatibilitätsbibliotheken zu verwenden.

Informationen zum Upgrade

Jeder Schritt des Upgradeprozesses ist so konzipiert, dass Sie die Bearbeitung der Quelle für Ihre Anwendung abschließen und sie dann ohne Unterbrechung kompilieren und ausführen können. Zusammenfassend gehen Sie so vor, um eine App zu aktualisieren:

  1. Fügen Sie Ihrer App die modularen Bibliotheken und die Kompatibilitätsbibliotheken hinzu.
  2. Aktualisieren Sie die Importanweisungen in Ihrem Code auf „compat“.
  3. Refaktorieren Sie den Code für ein einzelnes Produkt (z. B. Authentication) in den modularen Stil.
  4. Optional: Entfernen Sie an dieser Stelle die Kompatibilitätsbibliothek Authentication und den Kompatibilitätscode für Authentication, um die Vorteile der App-Größe für Authentication zu nutzen, bevor Sie fortfahren.
  5. Refaktorieren Sie die Funktionen für jedes Produkt (z. B. Cloud Firestore, FCM usw.) in den modularen Stil und kompilieren und testen Sie sie, bis alle Bereiche fertig sind.
  6. Aktualisieren Sie den Initialisierungscode auf den modularen Stil.
  7. Entfernen Sie alle verbleibenden Kompatibilitätsanweisungen und den Kompatibilitätscode aus Ihrer App.

Aktuelle Version des SDK herunterladen

Rufen Sie zuerst die modularen Bibliotheken und die Kompatibilitätsbibliotheken mit npm ab:

npm i firebase@13.2.0

# OR

yarn add firebase@13.2.0

Importe auf „compat“ aktualisieren

Damit Ihr Code nach dem Aktualisieren der Abhängigkeiten weiterhin funktioniert, ändern Sie Ihre Importanweisungen so, dass die „compat“-Version jedes Imports verwendet wird. Beispiel:

Vorher: Version 8 oder älter

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';

Nachher: compat

// compat packages are API compatible with namespaced code
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';

Refaktorierung in den modularen Stil

Während die APIs mit Namensraum auf einem Namespace- und Dienstmuster mit Punktverkettung basieren, wird Ihr Code beim modularen Ansatz hauptsächlich um Funktionen herum organisiert. In der modularen API geben das Paket firebase/app und andere Pakete keinen umfassenden Export zurück, der alle Methoden aus dem Paket enthält. Stattdessen exportieren die Pakete einzelne Funktionen.

In der modularen API werden Dienste als erstes Argument übergeben. Die Funktion verwendet dann die Details des Dienstes, um den Rest zu erledigen. Sehen wir uns anhand von zwei Beispielen an, wie das funktioniert. Dabei werden Aufrufe der Authentication- und Cloud Firestore-APIs refaktoriert.

Beispiel 1: Authentication-Funktion refaktorieren

Vorher: compat

Der Kompatibilitätscode ist mit dem Namespace-Code identisch, aber die Importe haben sich geändert.

import firebase from "firebase/compat/app";
import "firebase/compat/auth";

const auth = firebase.auth();
auth.onAuthStateChanged(user => { 
  // Check for user status
});

Nachher: modular

Die Funktion getAuth verwendet firebaseApp als ersten Parameter. Die Funktion onAuthStateChanged wird nicht wie in der API mit Namespace von der Instanz auth verkettet, sondern ist eine eigenständige Funktion, die auth als ersten Parameter verwendet.

import { getAuth, onAuthStateChanged } from "firebase/auth";

const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => {
  // Check for user status
});

Umgang mit Authentifizierungsmethode getRedirectResult aktualisieren

Die modulare API führt eine funktionsgefährdende Änderung in getRedirectResult ein. Wenn kein Weiterleitungsvorgang aufgerufen wird, gibt die modulare API null zurück. Die API mit Namensraum hat dagegen ein UserCredential mit einem null-Nutzer zurückgegeben.

Vorher: compat

const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
  return null;
}
return result;

Nachher: modular

const result = await getRedirectResult(auth);
// Provider of the access token could be Facebook, Github, etc.
if (result === null || provider.credentialFromResult(result) === null) {
  return null;
}
return result;

Beispiel 2: Cloud Firestore-Funktion refaktorieren

Vorher: compat

import "firebase/compat/firestore"

const db = firebase.firestore();
db.collection("cities").where("capital", "==", true)
    .get()
    .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            console.log(doc.id, " => ", doc.data());
        });
    })
    .catch((error) => {
        console.log("Error getting documents: ", error);
    });

Nachher: modular

Die Funktion getFirestore verwendet firebaseApp als ersten Parameter, der in einem früheren Beispiel von initializeApp zurückgegeben wurde. Beachten Sie, dass der Code zum Erstellen einer Abfrage in der modularen API ganz anders ist. Es gibt keine Verkettung und Methoden wie query oder where werden jetzt als eigenständige Funktionen bereitgestellt.

import { getFirestore, collection, query, where, getDocs } from "firebase/firestore";

const db = getFirestore(firebaseApp);

const q = query(collection(db, "cities"), where("capital", "==", true));

const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
});

Verweise auf Firestore DocumentSnapshot.exists aktualisieren

Die modulare API führt eine funktionsgefährdende Änderung ein, bei der das Attribut firestore.DocumentSnapshot.exists in eine Methode geändert wurde. Die Funktionalität ist im Wesentlichen dieselbe (Prüfung, ob ein Dokument vorhanden ist), aber Sie müssen Ihren Code so refaktorieren, dass die neuere Methode verwendet wird, wie hier gezeigt:

Before:compat

if (snapshot.exists) {
  console.log("the document exists");
}

Nachher: modular

if (snapshot.exists()) {
  console.log("the document exists");
}

Beispiel 3: Kombination von Namespace- und modularen Codestilen

Wenn Sie die Kompatibilitätsbibliotheken während des Upgrades verwenden, können Sie weiterhin Code mit Namespace zusammen mit Code verwenden, der für die modulare API refaktoriert wurde. Das bedeutet, dass Sie vorhandenen Namespace-Code für Cloud Firestore beibehalten können, während Sie Authentication oder anderen Firebase SDK-Code in den modularen Stil umgestalten, und Ihre App trotzdem mit beiden Codestilen erfolgreich kompilieren können. Das Gleiche gilt für Namespace- und modularen API-Code innerhalb eines Produkts wie Cloud Firestore. Neue und alte Codestile können nebeneinander existieren, solange Sie die Kompatibilitätspakete importieren:

import firebase from 'firebase/compat/app';
import 'firebase/compat/firestore';
import { getDoc } from 'firebase/firestore'

const docRef = firebase.firestore().doc();
getDoc(docRef);

Beachten Sie, dass Ihre App zwar kompiliert wird, Sie aber erst dann von der geringeren App-Größe des modularen Codes profitieren, wenn Sie die Kompatibilitätsanweisungen und den Code vollständig aus Ihrer App entfernt haben.

Initialisierungscode aktualisieren

Aktualisieren Sie den Initialisierungscode Ihrer App, um die modulare Syntax zu verwenden. Es ist wichtig, diesen Code nach dem Refaktorieren des gesamten Codes in Ihrer App zu aktualisieren. Der Grund dafür ist, dass firebase.initializeApp() den globalen Status sowohl für die kompatible als auch für die modulare API initialisiert, während die modulare Funktion initializeApp() nur den Status für die modulare API initialisiert.

Vorher: compat

import firebase from "firebase/compat/app"

firebase.initializeApp({ /* config */ });

Nachher: modular

import { initializeApp } from "firebase/app"

const firebaseApp = initializeApp({ /* config */ });

Kompatibilitätscode entfernen

Wenn Sie die Größenvorteile der modularen API nutzen möchten, sollten Sie alle Aufrufe in den oben gezeigten modularen Stil konvertieren und alle import "firebase/compat/*-Anweisungen aus Ihrem Code entfernen. Wenn Sie fertig sind, sollte es keine Verweise mehr auf den globalen Namespace firebase.* oder anderen Code im Stil der API mit Namespace geben.

Kompatibilitätsbibliothek aus dem Fenster verwenden

Die modulare API ist für die Verwendung mit Modulen und nicht mit dem window-Objekt des Browsers optimiert. In früheren Versionen der Bibliothek war das Laden und Verwalten von Firebase über den Namespace window.firebase möglich. Dies wird für die Zukunft nicht empfohlen, da es nicht möglich ist, nicht verwendeten Code zu entfernen. Die Kompatibilitätsversion des JavaScript SDK funktioniert jedoch mit dem window für Entwickler, die den modularen Upgradepfad nicht sofort beginnen möchten.

<script src="https://www.gstatic.com/firebasejs/13.2.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/13.2.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/13.2.0/firebase-auth-compat.js"></script>
<script>
   const firebaseApp = firebase.initializeApp({ /* Firebase config */ });
   const db = firebaseApp.firestore();
   const auth = firebaseApp.auth();
</script>

Die Kompatibilitätsbibliothek verwendet im Hintergrund modularen Code und stellt ihn mit derselben API wie die API mit Namensraum bereit. Weitere Informationen finden Sie in der API-Referenz mit Namensraum und in den Code-Snippets mit Namensraum. Diese Methode wird nicht für die langfristige Verwendung empfohlen, sondern als Einstieg für ein Upgrade auf die vollständig modulare Bibliothek.

Vorteile und Einschränkungen des modularen SDK

Das vollständig modularisierte SDK bietet gegenüber früheren Versionen folgende Vorteile:

  • Das modulare SDK ermöglicht eine drastisch reduzierte App-Größe. Es verwendet das moderne JavaScript-Modulformat, das „Tree-Shaking“-Verfahren ermöglicht, bei denen Sie nur die Artefakte importieren, die Ihre App benötigt. Je nach App kann das Tree-Shaking mit dem modularen SDK zu 80 % weniger Kilobyte führen als bei einer vergleichbaren App, die mit der API mit Namensraum erstellt wurde.
  • Das modulare SDK wird weiterhin von der laufenden Funktionsentwicklung profitieren, die API mit Namensraum jedoch nicht.