Upgrade von der Namespace-API auf die modulare API

Apps, die derzeit eine Firebase-Web-API mit Namensraum verwenden, von den compat Bibliotheken bis zur Version 8 oder früher, sollten eine Migration zur modularen API anhand der Anweisungen in diesem Handbuch in Betracht ziehen.

In diesem Leitfaden wird davon ausgegangen, dass Sie mit der Namespace-API vertraut sind und einen Modul-Bundler wie Webpack oder Rollup für Upgrades und die fortlaufende modulare App-Entwicklung nutzen.

Die Verwendung eines Modul-Bundlers in Ihrer Entwicklungsumgebung wird dringend empfohlen. Wenn Sie keine verwenden, können Sie die Hauptvorteile der modularen API in Form einer reduzierten 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 imaginären Web-App, die die SDKs Authentifizierung und Cloud Firestore verwendet. Durch das Durcharbeiten der Beispiele können Sie die Konzepte und praktischen Schritte beherrschen, die zum Aktualisieren aller unterstützten Firebase Web SDKs erforderlich sind.

Über die Namespace-Bibliotheken ( compat ).

Für das Firebase Web SDK stehen zwei Arten von Bibliotheken zur Verfügung:

  • Modular – eine neue API-Oberfläche, die das Tree-Shaking (Entfernen von ungenutztem Code) erleichtert, um Ihre Web-App so klein und schnell wie möglich zu machen.
  • Namespaced ( compat ) – eine vertraute API-Oberfläche, die vollständig mit den früheren Versionen des SDK kompatibel ist, sodass Sie ein Upgrade durchführen können, ohne Ihren gesamten Firebase-Code auf einmal zu ändern. Kompatible Bibliotheken haben kaum oder gar keine Größen- oder Leistungsvorteile gegenüber ihren Namensraum-Gegenstücken.

In diesem Handbuch wird davon ausgegangen, dass Sie die kompatiblen Bibliotheken nutzen, um Ihr Upgrade zu erleichtern. Mit diesen Bibliotheken können Sie neben Code, der für die modulare API umgestaltet wurde, weiterhin Namespace-Code verwenden. Dies bedeutet, dass Sie Ihre App während des Upgrade-Prozesses einfacher kompilieren und debuggen können.

Für Apps mit einem sehr geringen Zugriff auf das Firebase Web SDK – beispielsweise eine App, die nur einen einfachen Aufruf der Authentifizierungs-APIs durchführt – kann es praktisch sein, älteren Namespace-Code umzugestalten, ohne die kompatiblen Bibliotheken zu verwenden. Wenn Sie eine solche App aktualisieren, können Sie den Anweisungen in diesem Handbuch für „die modulare API“ folgen, ohne die kompatiblen Bibliotheken zu verwenden.

Über den Upgrade-Prozess

Jeder Schritt des Upgrade-Prozesses ist so festgelegt, dass Sie die Bearbeitung der Quelle für Ihre App abschließen und sie dann ohne Unterbrechung kompilieren und ausführen können. Zusammenfassend können Sie Folgendes tun, um eine App zu aktualisieren:

  1. Fügen Sie die modularen Bibliotheken und die kompatiblen Bibliotheken zu Ihrer App hinzu.
  2. Aktualisieren Sie die Importanweisungen in Ihrem Code, damit sie kompatibel sind.
  3. Refaktorieren Sie Code für ein einzelnes Produkt (z. B. Authentifizierung) in den modularen Stil.
  4. Optional: Entfernen Sie an dieser Stelle die kompatible Authentifizierungsbibliothek und den kompatiblen Code für die Authentifizierung, um den App-Größenvorteil für die Authentifizierung zu nutzen, bevor Sie fortfahren.
  5. Refaktorieren Sie die Funktionen für jedes Produkt (z. B. Cloud Firestore, FCM usw.) im modularen Stil, kompilieren und testen Sie, bis alle Bereiche vollständig sind.
  6. Aktualisieren Sie den Initialisierungscode auf den modularen Stil.
  7. Entfernen Sie alle verbleibenden Kompatibilitätsanweisungen und Kompatibilitätscodes aus Ihrer App.

Holen Sie sich die neueste Version des SDK

Rufen Sie zunächst die modularen Bibliotheken und kompatiblen Bibliotheken mit npm ab:

npm i firebase@10.9.0

# OR

yarn add firebase@10.9.0

Importe auf Kompatibilität aktualisieren

Damit Ihr Code nach der Aktualisierung Ihrer Abhängigkeiten weiterhin funktioniert, ändern Sie Ihre Importanweisungen so, dass für jeden Import die „kompatible“ Version verwendet wird. Zum Beispiel:

Vorher: Version 8 oder früher

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

Nachher: ​​kompatibel

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

Umgestaltung zum modularen Stil

Während die Namespace-APIs auf einem punktierten Namespace- und Servicemuster basieren, bedeutet der modulare Ansatz, dass Ihr Code hauptsächlich um Funktionen herum organisiert wird. In der modularen API geben das firebase/app Paket 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 anhand von zwei Beispielen an, wie dies funktioniert, indem Aufrufe an die APIs „Authentifizierung“ und „Cloud Firestore“ umgestaltet werden.

Beispiel 1: Refactoring einer Authentifizierungsfunktion

Vorher: kompatibel

Der Kompatibilitätscode ist identisch mit dem Namespace-Code, die Importe haben sich jedoch 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 getAuth Funktion verwendet firebaseApp als ersten Parameter. Die onAuthStateChanged Funktion ist nicht von der auth aus verkettet, wie dies in der Namespace-API der Fall wäre. Stattdessen handelt es sich um eine kostenlose Funktion, deren erster Parameter auth ist.

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

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

Aktualisieren Sie die Behandlung der Auth-Methode getRedirectResult

Die modulare API führt eine bahnbrechende Änderung in getRedirectResult ein. Wenn keine Umleitungsoperation aufgerufen wird, gibt die modulare API null zurück, im Gegensatz zur Namespace-API, die ein UserCredential mit einem null zurückgab.

Vorher: kompatibel

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: kompatibel

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 sehr unterschiedlich ist. Es gibt keine Verkettung und Methoden wie query oder where werden jetzt als freie 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());
});

Aktualisieren Sie Verweise auf Firestore DocumentSnapshot.exists

Die modulare API führt eine bahnbrechende Ä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 umgestalten, um die neuere Methode wie gezeigt zu verwenden:

Vorher:kompatibel

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

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

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

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

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

Initialisierungscode aktualisieren

Aktualisieren Sie den Initialisierungscode Ihrer App, um modulare Syntax zu verwenden. Es ist wichtig, diesen Code zu aktualisieren , nachdem Sie die Umgestaltung des gesamten Codes in Ihrer App abgeschlossen haben. Dies liegt daran, dass firebase.initializeApp() den globalen Status sowohl für die kompatible als auch für die modulare API initialisiert, während die Funktion modular initializeApp() nur den Status für modular initialisiert.

Vorher: kompatibel

import firebase from "firebase/compat/app"

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

Nachher: ​​modular

import { initializeApp } from "firebase/app"

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

Kompatibilitätscode entfernen

Um die Größenvorteile 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 Referenzen mehr vorhanden sein zum globalen Namespace firebase.* oder einem anderen Code im Namespace-API-Stil.

Verwenden der kompatiblen Bibliothek aus dem Fenster

Die modulare API ist für die Arbeit mit Modulen und nicht mit dem window des Browsers optimiert. Frühere Versionen der Bibliothek ermöglichten das Laden und Verwalten von Firebase mithilfe des Namespace window.firebase . Dies wird für die Zukunft nicht empfohlen, da die Entfernung von ungenutztem Code dadurch nicht möglich ist. Allerdings funktioniert die kompatible Version des JavaScript SDK mit dem window für Entwickler, die nicht sofort mit dem modularen Upgrade-Pfad beginnen möchten.

<script src="https://www.gstatic.com/firebasejs/10.9.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.9.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.9.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 unter der Haube und stellt ihm dieselbe API wie die Namespace-API zur Verfügung. Dies bedeutet, dass Sie für Einzelheiten auf die Namespace-API-Referenz und die Namespace-Codefragmente verweisen können. Diese Methode wird nicht für den Langzeitgebrauch 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 übernimmt das moderne JavaScript-Modulformat und ermöglicht „Tree Shaking“-Praktiken, bei denen Sie nur die Artefakte importieren, die Ihre App benötigt. Abhängig von Ihrer App kann das Tree-Shaking mit dem modularen SDK zu 80 % weniger Kilobyte führen als eine vergleichbare App, die mit der Namespace-API erstellt wurde.
  • Das modulare SDK wird weiterhin von der fortlaufenden Funktionsentwicklung profitieren, die Namespace-API dagegen nicht.