Von der API mit Namespace zur modularen Anwendung wechseln

Apps, in denen eine Firebase-Web-API mit Namespace aus den compat-Bibliotheken bis einschließlich Version 8 oder früher verwendet wird, sollten gemäß der Anleitung in diesem Leitfaden zur modularen API migriert werden.

In dieser Anleitung wird davon ausgegangen, dass Sie mit der Namespaced API vertraut sind und einen Modul-Bundler wie webpack oder Rollup für die Aktualisierung und die laufende modulare App-Entwicklung verwenden.

Es wird dringend empfohlen, in Ihrer Entwicklungsumgebung einen Modul-Bundler zu verwenden. 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 Aktualisierungsschritte in dieser Anleitung 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 kennenlernen, die für die Aktualisierung aller unterstützten Firebase-Web-SDKs erforderlich sind.

Namespaced-Bibliotheken (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 Web-App so klein und schnell wie möglich ist.
  • Mit Namespace (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 Ihren gesamten Firebase-Code auf einmal ändern zu müssen. Kompatibilitätsbibliotheken bieten im Vergleich zu ihren Namensraum-Pendants kaum oder gar keine Vorteile in Bezug auf Größe oder Leistung.

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

Bei Apps, die das Firebase Web SDK nur in sehr geringem Umfang nutzen, z. B. bei Apps, die nur einen einfachen Aufruf der Authentication APIs ausführen, kann es sinnvoll sein, den alten Code mit Namespaces zu refaktorieren, ohne die Compat-Bibliotheken zu verwenden. Wenn Sie eine solche App aktualisieren, können Sie der Anleitung in diesem Leitfaden für die modulare API folgen, ohne die Compat-Bibliotheken zu verwenden.

Informationen zum Upgradevorgang

Jeder Schritt des Upgradeprozesses ist so konzipiert, dass Sie die Quelle für Ihre App bearbeiten und sie dann ohne Probleme kompilieren und ausführen können. Zusammenfassend lässt sich sagen, dass Sie zum Aktualisieren einer App Folgendes tun müssen:

  1. Fügen Sie Ihrer App die modularen Bibliotheken und die Compat-Bibliotheken 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 Authentication-kompatible Bibliothek und den kompatiblen Code für Authentication, um die App-Größe für Authentication zu optimieren, bevor Sie fortfahren.
  5. Lagern Sie Funktionen für jedes Produkt (z. B. Cloud Firestore, FCM usw.) in Module aus und kompilieren und testen Sie sie, bis alle Bereiche abgeschlossen sind.
  6. Aktualisieren Sie den Initialisierungscode auf den modularen Stil.
  7. Entfernen Sie alle verbleibenden Kompatibilitätsanweisungen und den Kompatibilitätscode aus Ihrer App.

Neueste Version des SDK herunterladen

Rufen Sie die modularen Bibliotheken und die Compat-Bibliotheken mit npm ab:

npm i firebase@12.0.0

# OR

yarn add firebase@12.0.0

Importe auf „compat“ aktualisieren

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

Vorher: Version 8 oder früher

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';

Auf modularen Stil umstellen

Die APIs mit Namespace basieren zwar auf einem durch Punkte verketteten Namespace- und Dienstmuster, der modulare Ansatz bedeutet jedoch, dass Ihr Code hauptsächlich um Funktionen organisiert wird. In der modularen API wird mit dem Paket firebase/app und anderen Paketen kein umfassender Export zurückgegeben, der alle Methoden aus dem Paket enthält. Stattdessen werden einzelne Funktionen exportiert.

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 an, wie das in zwei Beispielen funktioniert, in denen Aufrufe der APIs Authentication und Cloud Firestore refaktoriert werden.

Beispiel 1: Refactoring einer Authentication-Funktion

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 von der auth-Instanz verkettet, wie es in der API mit Namespace der Fall wäre. Stattdessen ist sie eine kostenlose Funktion, die auth als ersten Parameter verwendet.

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

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

Aktualisierung der Verarbeitung der Authentifizierungsmethode getRedirectResult

Die modulare API führt eine nicht abwärtskompatible Änderung in getRedirectResult ein. Wenn kein Weiterleitungsvorgang aufgerufen wird, gibt die modulare API null zurück. Die API mit Namespace gibt dagegen ein UserCredential mit einem null-Nutzer zurück.

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: Refactoring einer Cloud Firestore-Funktion

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. Der Code zum Erstellen einer Abfrage unterscheidet sich in der modularen API erheblich. Es gibt kein Chaining und Methoden wie query oder where werden jetzt als kostenlose 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 aktualisieren DocumentSnapshot.exists

Die modulare API führt eine nicht abwärtskompatible Änderung ein, bei der das Attribut firestore.DocumentSnapshot.exists in eine Methode geändert wurde. Die Funktionalität ist im Wesentlichen dieselbe (es wird geprüft, ob ein Dokument vorhanden ist), aber Sie müssen Ihren Code so umgestalten, dass die neuere Methode verwendet wird:

Vorher:compat

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

Nachher: modular

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

Beispiel 3: Kombinieren von Namespaces und modularem Code

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

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

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

Ihre App wird zwar kompiliert, aber die Vorteile des modularen Codes in Bezug auf die App-Größe können Sie erst nutzen, wenn Sie die Kompatibilitätsanweisungen und den Code vollständig aus Ihrer App entfernt haben.

Initialisierungscode aktualisieren

Aktualisieren Sie den Initialisierungscode Ihrer App, damit die modulare Syntax verwendet wird. Es ist wichtig, diesen Code zu aktualisieren, nachdem Sie den gesamten Code in Ihrer App refaktoriert haben. Das liegt daran, dass mit firebase.initializeApp() der globale Status für die Compat- und die modularen APIs initialisiert wird, während mit der modularen Funktion initializeApp() nur der Status für die modularen APIs initialisiert wird.

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

Damit Sie die Vorteile der modularen API in Bezug auf die Größe nutzen können, sollten Sie schließlich alle Aufrufe in den oben gezeigten modularen Stil umwandeln und alle import "firebase/compat/*-Anweisungen aus Ihrem Code entfernen. Wenn Sie fertig sind, sollten keine Verweise auf den globalen Namespace firebase.* oder anderen Code im API-Stil mit Namespace mehr vorhanden sein.

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. Diese Methode wird nicht mehr empfohlen, da sie keine Entfernung von ungenutztem Code ermöglicht. Die Kompatibilitätsversion des JavaScript SDK funktioniert jedoch mit der window für Entwickler, die nicht sofort mit dem modularen Upgrade beginnen möchten.

<script src="https://www.gstatic.com/firebasejs/12.0.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.0.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.0.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 modularen Code und stellt ihn mit derselben API wie die API mit Namespace bereit. Das bedeutet, dass Sie für Details auf die Referenz zur API mit Namespace und auf Code-Snippets mit Namespace verweisen können. Diese Methode wird nicht für die langfristige Verwendung empfohlen, sondern als Einstieg in die Migration zur vollständig modularen 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 drastische Reduzierung der App-Größe. Es verwendet das moderne JavaScript-Modulformat, das „Tree Shaking“ ermöglicht. Dabei werden nur die Artefakte importiert, die Ihre App benötigt. Je nach App kann das Tree Shaking mit dem modularen SDK zu einer Reduzierung der Kilobyte um 80% führen im Vergleich zu einer vergleichbaren App, die mit der Namespaced API erstellt wurde.
  • Das modulare SDK wird weiterhin von der laufenden Funktionsentwicklung profitieren, die API mit Namespace jedoch nicht.