Von der API mit Namespace zur modularen Anwendung wechseln

Apps, die eine beliebige Firebase-Web-API mit Namespace verwenden, von den compat-Bibliotheken bis 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 Namespace vertraut sind und einen Modul-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 Upgrade-Schritte in diesem Leitfaden basieren auf einer fiktiven Web-App, die die Authentication und Cloud Firestore SDKs verwendet. Wenn Sie die Beispiele durcharbeiten, können Sie die Konzepte und praktischen Schritte beherrschen, die für das 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, um Ihre Web-App so klein und schnell wie möglich zu machen.
  • 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 den gesamten Firebase-Code auf einmal ändern zu müssen. Bibliotheken mit Namespace bieten im Vergleich zu ihren Pendants mit Namespace nur geringe oder gar keine Vorteile in Bezug auf Größe oder Leistung.

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

Bei Apps mit einer sehr geringen Nutzung des Firebase-Web-SDK, z. B. einer App, die nur einen einfachen Aufruf an die Authentication APIs ausführt, kann es sinnvoll sein, älteren Code mit Namespace ohne Verwendung der Bibliotheken mit Namespace zu refaktorieren. Wenn Sie ein Upgrade für eine solche App durchführen, können Sie der Anleitung in diesem Leitfaden für die modulare API folgen, ohne die Bibliotheken mit Namespace zu verwenden.

Informationen zum Upgrade-Prozess

Jeder Schritt des Upgrade-Prozesses ist so konzipiert, dass Sie die Bearbeitung des Quellcodes für Ihre App abschließen und sie dann ohne Fehler kompilieren und ausführen können. Zusammenfassend lässt sich sagen, dass Sie für das Upgrade einer App Folgendes tun müssen:

  1. Fügen Sie Ihrer App die modularen Bibliotheken und die Bibliotheken mit Namespace 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 Bibliothek mit Namespace und den Code mit Namespace für Authentication, um die Vorteile der App-Größe für Authentication zu nutzen, bevor Sie fortfahren.
  5. Refaktorieren Sie Funktionen für jedes Produkt (z. B. Cloud Firestore, FCM, usw.) in den modularen Stil 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 Anweisungen und den Code mit Namespace aus Ihrer App.

Neueste Version des SDK herunterladen

Laden Sie zuerst die modularen Bibliotheken und die Bibliotheken mit Namespace mit npm herunter:

npm i firebase@12.15.0

# OR

yarn add firebase@12.15.0

Importe auf „compat“ aktualisieren

Damit Ihr Code nach dem Aktualisieren Ihrer Abhängigkeiten weiterhin funktioniert, ändern Sie Ihre Importanweisungen so, 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';

In den modularen Stil refaktorieren

Während die APIs mit Namespace auf einem Namespace und einem Dienstmuster mit Punktverkettung basieren, wird Ihr Code beim modularen Ansatz hauptsächlich um Funktionen 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 und 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 an die Authentication und Cloud Firestore APIs refaktoriert werden.

Beispiel 1: Authentication Funktion refaktorieren

Vorher: compat

Der Code mit Namespace ist mit dem Code mit Namespace 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 onAuthStateChanged Funktion wird nicht von der authInstanz 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
});

Umgang mit der Auth-Methode getRedirectResult aktualisieren

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

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: eine 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 sich der Code zum Erstellen einer Abfrage in der modularen API stark unterscheidet. Es gibt keine Verkettung und Methoden wie query oder where werden jetzt als kostenlose Funktionen verfügbar gemacht.

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 nicht abwärtskompatible Änderung ein, bei der die Eigenschaft firestore.DocumentSnapshot.exists in eine Methode geändert wurde. Die Funktionalität ist im Wesentlichen dieselbe (Testen, ob ein Dokument vorhanden ist), aber Sie müssen Ihren Code so refaktorieren, 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: Code-Stile mit Namespace und modular kombinieren

Wenn Sie die Bibliotheken mit Namespace während des Upgrades verwenden, können Sie weiterhin Code mit Namespace neben Code verwenden, der für die modulare API refaktoriert wurde. So können Sie vorhandenen Code mit Namespace für Cloud Firestore beibehalten, während Sie Authentication oder anderen Firebase-SDK-Code in den modularen Stil refaktorieren. Ihre App kann weiterhin mit beiden Code Stilen erfolgreich kompiliert werden. Dasselbe gilt für API-Code mit Namespace und modularen API-Code innerhalb eines Produkts wie Cloud Firestore. Neue und alte Code-Stile können nebeneinander existieren, solange Sie die Pakete mit Namespace 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 den Vorteilen der App-Größe des modularen Codes profitieren, wenn Sie die Anweisungen und den Code mit Namespace 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 zu aktualisieren, nachdem Sie das Refactoring des gesamten Codes in Ihrer App abgeschlossen haben. Das liegt daran, dass firebase.initializeApp() den globalen Status für die APIs mit Namespace und die modularen APIs initialisiert, während die modulare initializeApp() Funktion nur den Status für die modularen APIs initialisiert.

Vorher: compat

import firebase from "firebase/compat/app"

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

Nachher: modular

import { initializeApp } from "firebase/app"

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

Code mit Namespace entfernen

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

Bibliothek mit Namespace 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 konnten Firebase mit dem Namespace window.firebase geladen und verwaltet werden. Das wird in Zukunft nicht mehr empfohlen, da nicht verwendeter Code nicht entfernt werden kann. Die Version mit Namespace des JavaScript SDK funktioniert jedoch mit dem window für Entwickler, die nicht sofort mit dem modularen Upgrade beginnen möchten.

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

Die Bibliothek mit Namespace verwendet modularen Code und bietet dieselbe API wie die API mit Namespace. Weitere Informationen finden Sie in der Referenz zur API mit Namespace und in den Code-Snippets mit Namespace. Diese Methode wird nicht für die langfristige Verwendung empfohlen, sondern als Einstieg in das 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 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 Tree Shaking mit dem modularen SDK zu 80% weniger Kilobyte führen als bei einer vergleichbaren App, die mit der API mit Namespace erstellt wurde.
  • Das modulare SDK profitiert weiterhin von der laufenden Funktionsentwicklung, während die API mit Namespace nicht weiterentwickelt wird.