Wenn Sie bereits mit dem Firebase JS SDK oder anderen Firebase-Client-SDKs gearbeitet haben, kennen Sie wahrscheinlich die FirebaseApp-Schnittstelle und wissen, wie Sie damit App-Instanzen konfigurieren. Um ähnliche Vorgänge auf dem Server zu ermöglichen, bietet Firebase FirebaseServerApp.
FirebaseServerApp ist eine Variante von FirebaseApp für die Verwendung in Umgebungen mit serverseitigem Rendering (SSR). Es enthält Tools, um Firebase-Sitzungen fortzusetzen, die die Grenze zwischen clientseitigem Rendering (CSR) und serverseitigem Rendering überschreiten. Diese
Tools und Strategien können dazu beitragen, dynamische Webanwendungen zu verbessern, die mit Firebase erstellt und
in Google-Umgebungen wie
Firebase App Hostingbereitgestellt werden.
Verwenden Sie FirebaseServerApp für folgende Zwecke:
- Serverseitigen Code im Kontext des Nutzers ausführen, im Gegensatz zum Firebase Admin SDK, das vollständige Administratorrechte hat.
- Die Verwendung von App Check in SSR-Umgebungen aktivieren.
- Eine Firebase Auth-Sitzung fortsetzen, die auf dem Client erstellt wurde.
Der Lebenszyklus von FirebaseServerApp
Frameworks für serverseitiges Rendering (SSR) und andere Nicht-Browser-Laufzeiten wie Cloud-Worker optimieren die Initialisierungszeit, indem sie Ressourcen für mehrere Ausführungen wiederverwenden. FirebaseServerApp ist für diese Umgebungen konzipiert und verwendet einen Mechanismus zur Referenzzählung. Wenn eine App initializeServerApp mit denselben Parametern wie ein vorheriges initializeServerApp aufruft, erhält sie dieselbe FirebaseServerApp-Instanz, die bereits initialisiert wurde. Dadurch werden unnötiger Initialisierungsaufwand und Speicherzuweisungen reduziert. Wenn deleteApp für eine FirebaseServerApp-Instanz aufgerufen wird, wird die Referenzanzahl reduziert. Die Instanz wird freigegeben, nachdem die Referenzanzahl null erreicht hat.
FirebaseServerApp-Instanzen bereinigen
Es kann schwierig sein zu wissen, wann deleteApp für eine FirebaseServerApp-Instanz aufgerufen werden muss, insbesondere wenn viele asynchrone Vorgänge parallel ausgeführt werden. Das Feld releaseOnDeref von FirebaseServerAppSettings kann dies vereinfachen. Wenn Sie releaseOnDeref eine Referenz zu einem Objekt mit der Lebensdauer des Anforderungsbereichs zuweisen (z. B. das Headerobjekt der SSR-Anfrage), reduziert FirebaseServerApp die Referenzanzahl, wenn das Framework das Headerobjekt freigibt. Dadurch wird Ihre FirebaseServerApp-Instanz automatisch bereinigt.
Hier ein Beispiel für die Verwendung von releaseOnDeref:
/// Next.js
import { headers } from 'next/headers'
import { FirebaseServerAppSettings, initializeServerApp} from "firebase/app";
export default async function Page() {
const headersObj = await headers();
let appSettings: FirebaseServerAppSettings = {};
appSettings.releaseOnDeref = headersObj;
const serverApp = initializeServerApp(firebaseConfig, appSettings);
...
}
Authentifizierte Sitzungen fortsetzen, die auf dem Client erstellt wurden
Wenn eine Instanz von FirebaseServerApp mit einem Auth-ID-Token initialisiert wird, können authentifizierte Nutzersitzungen zwischen den Umgebungen für clientseitiges Rendering (CSR) und serverseitiges Rendering (SSR) überbrückt werden. Instanzen des Firebase Auth SDK, die mit einem FirebaseServerApp-Objekt initialisiert wurden, das ein Auth-ID-Token enthält, versuchen, den Nutzer bei der Initialisierung anzumelden, ohne dass die Anwendung Anmeldemethoden aufrufen muss.
Durch die Bereitstellung eines Auth-ID-Tokens können Apps alle Anmeldemethoden von Auth auf dem Client verwenden. So wird sichergestellt, dass die Sitzung serverseitig fortgesetzt wird, auch bei Anmeldemethoden, die eine Nutzerinteraktion erfordern. Außerdem können so ressourcenintensive Vorgänge wie authentifizierte Firestore-Abfragen auf den Server ausgelagert werden, was die Rendering-Leistung Ihrer App verbessern sollte.
/// Next.js
import { initializeServerApp } from "firebase/app";
import { getAuth } from "firebase/auth";
// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
// ...
};
const firebaseServerAppSettings = {
authIdToken: token // See "Pass client tokens to the server side
// rendering phase" for an example on how transmit
// the token from the client and the server.
}
const serverApp =
initializeServerApp(firebaseConfig,
firebaseServerAppSettings);
const serverAuth = getAuth(serverApp);
// FirebaseServerApp and Auth will now attempt
// to sign in the current user based on provided
// authIdToken.
App Check in SSR-Umgebungen verwenden
Die App Check-Erzwingung basiert auf einer App Check SDK-Instanz, die von Firebase SDKs verwendet wird, um intern getToken aufzurufen. Das resultierende Token wird dann in Anfragen an alle Firebase-Dienste eingefügt, sodass das Back-End die App validieren kann.
Da das App Check SDK jedoch einen Browser benötigt, um auf bestimmte Heuristiken für die App-Validierung zuzugreifen, kann es nicht in Serverumgebungen initialisiert werden.
FirebaseServerApp bietet eine Alternative. Wenn bei der Initialisierung von FirebaseServerApp ein vom Client generiertes App Check-Token bereitgestellt wird, wird es von den Firebase-Produkt-SDKs beim Aufrufen von Firebase-Diensten verwendet. Eine App Check SDK-Instanz ist dann nicht mehr erforderlich.
/// Next.js
import { initializeServerApp } from "firebase/app";
// Replace the following with your app's
// Firebase project configuration
const firebaseConfig = {
// ...
};
const firebaseServerAppSettings = {
appCheckToken: token // See "Pass client tokens to the server side
// rendering phase" for an example on how transmit
// the token from the client and the server.
}
const serverApp =
initializeServerApp(firebaseConfig,
firebaseServerAppSettings);
// The App Check token will now be appended to all Firebase service requests.
Client-Tokens an die serverseitige Renderingphase übergeben
Verwenden Sie einen Service Worker, um authentifizierte Auth-ID-Tokens (und App Check-Tokens) vom Client an die serverseitige Renderingphase (SSR) zu übertragen. Bei diesem Ansatz werden Fetch-Anfragen abgefangen, die SSR auslösen, und die Tokens werden an die Anfrageheader angehängt.
Eine Referenzimplementierung
eines Firebase Auth-Service Workers finden Sie unter Sitzungsverwaltung mit Service
Workers. Unter Serverseitige
Änderungen finden Sie Code,
der zeigt, wie diese Tokens aus den Headern geparst werden, um sie bei der Verwendung in
FirebaseServerApp Initialisierung zu verwenden.
Firestore in SSR-Umgebungen verwenden
Beim Erstellen von Webanwendungen mit serverseitigem Rendering (SSR) müssen Sie häufig Daten zwischen dem Server und dem Client freigeben, um die Leistung und die Nutzerfreundlichkeit zu optimieren. Das Firestore SDK bietet Serialisierungstools, mit denen Sie Snapshots und bestimmte Datentypen auf dem Server erfassen und direkt an Ihre clientseitigen Komponenten übergeben können. Durch diesen Prozess werden redundante Abrufe vermieden, da der Client den Status mit den Daten auffüllen kann, die während der SSR-Phase vorab abgerufen wurden. Außerdem können Sie von diesen serialisierten Status zu Echtzeit-Listenern wechseln, um sicherzustellen, dass Ihre Anwendung mit der Datenbank synchronisiert bleibt.
In diesem Abschnitt wird beschrieben, wie Sie Daten, die während der serverseitigen Renderingphase (SSR) abgerufen wurden, in clientseitigen Komponenten wiederverwenden.
Datentypen serialisieren
Bestimmte Firestore-Datentypen bieten eine toJSON-Methode, um ihre Daten in ein serialisierbares Format zu konvertieren. Dazu gehören Instanzen von Objekten wie Bytes, GeoPoint, Timestamp und VectorValue.
Sobald die Daten im JSON-Format vorliegen, können Sie sie über Standard-Framework-Mechanismen vom Server an den Client übergeben oder als Parameter an Komponenten, die die Grenze überschreiten. Beispiel:
import {
Bytes
} from 'firebase/firestore';
const BYTES_DATA = new Uint8Array([0, 1, 2, 3, 4, 5]);
const bytes = Bytes.fromUint8Array(BYTES_DATA);
const bytesJSON = bytes.toJSON();
Datentypen deserialisieren
Firestore-Datentypen enthalten die statische Methode fromJSON, um die serialisierten Daten in einen verwendbaren Firestore-Datentyp zu konvertieren.
Im folgenden Beispiel wird ein Bytes-Datentyp deserialisiert:
import {
Bytes
} from 'firebase/firestore';
// Assuming the same `bytesJSON` variable from the previous example.
const deserializedBytes = Bytes.fromJSON(bytesJSON);
Firestore-Snapshots serialisieren und deserialisieren
Ähnlich wie bei Firestore-Datentypen können Sie Instanzen von DocumentSnapshot und QuerySnapshot mit toJSON serialisieren. Um sie zu deserialisieren, müssen Sie jedoch die eigenständigen Funktionen documentSnapshotFromJSON und querySnapshotFromJSON anstelle einer statischen fromJSON-Methode verwenden.
Die querySnapshot-Ergebnisse eines query-Vorgangs können
mit der Methode toJSON serialisiert werden:
import {
collection,
getDocs,
query,
querySnapshotFromJSON
} from 'firebase/firestore';
// Assuming a configured instance of Firestore in the variable `firestore`.
const queryRef = query(collection(firestore, QUERY_PATH));
const querySnapshot = await getDocs(queryRef);
const querySnapshotJson = querySnapshot.toJSON();
Anschließend können diese Daten deserialisiert werden:
import {
querySnapshotFromJSON
} from 'firebase/firestore';
// deserializedSnapshot is an object of type QuerySnapshot:
const deserializedSnapshot =
querySnapshotFromJSON(firestore, querySnapshotJson);
Listener mit serialisierten Snapshots
Die während der SSR-Phase abgefragten Daten sind zwar für das erste CSR-Rendering wertvoll, Sie müssen den Firestore-Dienst aber möglicherweise weiterhin auf Echtzeit-Updates dieser Informationen überwachen.
Wenn Ihre App diese Echtzeit-Updates benötigt, können Sie die onSnapshotResume
Funktion verwenden, um Firestore SnapshotListeners mit serialisierten Snapshot
Daten zu initialisieren. Beispiel:
const observer = {
next: (qs) => {
console.log("onSnapshot invoked: ", qs.data());
},
error: (e) => {
console.log("error callback invoked: ", e.toString());
}
};
const unsubscribe = onSnapshotResume(firestore, querySnapshotJson, observer);