Jeśli pracujesz z pakietem Firebase JS SDK lub innymi pakietami Firebase SDK dla klientów, prawdopodobnie znasz interfejs FirebaseApp i wiesz, jak go używać do konfigurowania instancji aplikacji. Aby ułatwić podobne operacje po stronie serwera, Firebase udostępnia FirebaseServerApp.
FirebaseServerApp to wariant FirebaseApp do użycia w środowiskach renderowania po stronie serwera (SSR). Zawiera narzędzia do kontynuowania sesji Firebase, które obejmują renderowanie po stronie klienta i renderowanie po stronie serwera. Te narzędzia i strategie mogą pomóc w ulepszaniu dynamicznych aplikacji internetowych utworzonych za pomocą Firebase i wdrożonych w środowiskach Google, takich jak Firebase App Hosting.
Korzystaj z FirebaseServerApp, aby:
- wykonywać kod po stronie serwera w kontekście użytkownika, w przeciwieństwie do pakietu Firebase Admin SDK, który ma pełne uprawnienia administracyjne;
- Włącz korzystanie ze Sprawdzania aplikacji w środowiskach SSR.
- Kontynuowanie sesji uwierzytelniania Firebase utworzonej na kliencie.
Cykl życia FirebaseServerApp
Frameworki renderowania po stronie serwera (SSR) i inne środowiska wykonawcze inne niż przeglądarka, takie jak usługi w chmurze, optymalizują czas inicjowania, ponownie wykorzystując zasoby w wielu wykonaniach. FirebaseServerApp jest przeznaczona do obsługi tych środowisk dzięki zastosowaniu mechanizmu liczby referencyjnej. Jeśli aplikacja wywoła funkcję
initializeServerApp z tymi samymi parametrami co poprzednia funkcja
initializeServerApp, otrzyma tę samą instancję FirebaseServerApp, która została już zainicjowana. Pozwala to ograniczyć niepotrzebne koszty inicjowania i alokacji pamięci. Gdy funkcja deleteApp jest wywoływana w przypadku instancji FirebaseServerApp, zmniejsza liczbę odwołań, a instancja jest zwalniana po osiągnięciu przez liczbę odwołań zera.
Czyszczenie instancji FirebaseServerApp
Trudno jest określić, kiedy wywołać deleteApp na instancji FirebaseServerApp, zwłaszcza jeśli równolegle wykonujesz wiele operacji asynchronicznych. Ułatwia to pole releaseOnDeref w FirebaseServerAppSettings. Jeśli przypiszesz releaseOnDeref odwołanie do obiektu o czasie życia zakresu żądania (np. do obiektu nagłówków żądania SSR), FirebaseServerApp zmniejszy liczbę odwołań, gdy framework odzyska obiekt nagłówków. Spowoduje to automatyczne wyczyszczenie instancji FirebaseServerApp.
Oto przykład użycia właściwości 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);
...
}
Wznawianie uwierzytelnionych sesji utworzonych na kliencie
Gdy instancja FirebaseServerApp jest inicjowana za pomocą tokena identyfikatora uwierzytelniania, umożliwia to połączenie uwierzytelnionych sesji użytkownika między środowiskami renderowania po stronie klienta (CSR) i renderowania po stronie serwera (SSR). Instancje pakietu SDK Uwierzytelnianie Firebase zainicjowane za pomocą obiektu FirebaseServerApp zawierającego token identyfikatora uwierzytelniania będą próbować zalogować użytkownika podczas inicjowania bez konieczności wywoływania przez aplikację jakichkolwiek metod logowania.
Podanie tokena identyfikatora autoryzacji umożliwia aplikacjom korzystanie z dowolnych metod logowania Auth po stronie klienta, co zapewnia kontynuowanie sesji po stronie serwera, nawet w przypadku metod logowania wymagających interakcji użytkownika. Umożliwia też przenoszenie na serwer operacji wymagających dużej mocy obliczeniowej, takich jak uwierzytelnione zapytania do Firestore, co powinno zwiększyć wydajność renderowania aplikacji.
/// 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.
Używanie usługi Sprawdzanie aplikacji w środowiskach SSR
Wymuszanie Sprawdzania aplikacji opiera się na instancji pakietu SDK Sprawdzania aplikacji, z której korzystają pakiety SDK Firebase, aby wewnętrznie wywoływać getToken. Wynikowy token jest następnie dołączany do żądań wysyłanych do wszystkich usług Firebase, co umożliwia backendowi weryfikację aplikacji.
Pakiet SDK Sprawdzania aplikacji potrzebuje jednak przeglądarki, aby uzyskać dostęp do określonych heurystyk na potrzeby weryfikacji aplikacji, więc nie można go zainicjować w środowiskach serwerowych.
FirebaseServerApp podaje alternatywę. Jeśli podczas FirebaseServerAppinicjowaniaFirebaseServerApp zostanie podany token Sprawdzania aplikacji wygenerowany przez klienta, będzie on używany przez pakiety SDK usług Firebase podczas wywoływania usług Firebase, co eliminuje potrzebę instancji pakietu SDK Sprawdzania aplikacji.
/// 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.
Przekazywanie tokenów klienta do fazy renderowania po stronie serwera
Aby przesyłać uwierzytelnione tokeny identyfikatora Uwierzytelniania (i tokeny Sprawdzania aplikacji) z klienta do fazy renderowania po stronie serwera (SSR), użyj skryptu service worker. To podejście polega na przechwytywaniu żądań pobierania, które wywołują renderowanie po stronie serwera, i dołączaniu tokenów do nagłówków żądań.
Więcej informacji o implementacji skryptu service worker uwierzytelniania Firebase znajdziesz w artykule Zarządzanie sesjami za pomocą skryptów service worker. W sekcji Zmiany po stronie serwera znajdziesz kod, który pokazuje, jak analizować te tokeny z nagłówków do użycia podczas inicjowania FirebaseServerApp.
Używanie Firestore w środowiskach SSR
Podczas tworzenia aplikacji internetowych z renderowaniem po stronie serwera (SSR) często trzeba udostępniać dane między serwerem a klientem, aby zoptymalizować wydajność i wrażenia użytkowników. Pakiet SDK Firestore udostępnia narzędzia do serializacji, które umożliwiają przechwytywanie migawek i określonych typów danych na serwerze oraz przekazywanie ich bezpośrednio do komponentów po stronie klienta. Ten proces eliminuje zbędne pobieranie danych, umożliwiając klientowi uzupełnianie stanu za pomocą danych wstępnie pobranych podczas renderowania po stronie serwera. Możesz też przejść z tych stanów serializowanych na odbiorniki w czasie rzeczywistym, dzięki czemu aplikacja pozostanie zsynchronizowana z bazą danych.
W tej sekcji opisujemy, jak ponownie wykorzystać dane pobrane podczas renderowania po stronie serwera w komponentach po stronie klienta.
Serializowanie typów danych
Niektóre typy danych Firestore udostępniają metodę toJSON, która umożliwia konwertowanie danych na format serializowalny. Obejmują one instancje obiektów, takich jak Bytes, GeoPoint, Timestamp i VectorValue.
Gdy dane będą już w formacie JSON, możesz przekazać je z serwera do klienta za pomocą standardowych mechanizmów platformy lub jako parametry komponentów, które obejmują tę różnicę. Przykład:
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();
Deserializacja typów danych
Typy danych Firestore zawierają metodę statyczną fromJSON, która umożliwia przekształcenie serializowanych danych w typ danych Firestore, na którym można wykonywać operacje.
Na przykład poniższy kod deserializuje typ danych Bytes:
import {
Bytes
} from 'firebase/firestore';
// Assuming the same `bytesJSON` variable from the previous example.
const deserializedBytes = Bytes.fromJSON(bytesJSON);
Serializowanie i deserializowanie zrzutów Firestore
Podobnie jak w przypadku typów danych Firestore, instancje DocumentSnapshot i QuerySnapshot możesz serializować za pomocą toJSON. Aby je jednak deserializować, musisz użyć samodzielnych funkcji documentSnapshotFromJSON i querySnapshotFromJSON zamiast statycznej metody fromJSON.
Na przykład querySnapshot wyniki działania query można serializować za pomocą metody toJSON:
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();
Następnie można zdeserializować te dane:
import {
querySnapshotFromJSON
} from 'firebase/firestore';
// deserializedSnapshot is an object of type QuerySnapshot:
const deserializedSnapshot =
querySnapshotFromJSON(firestore, querySnapshotJson);
Detektory zrzutów z zserializowanymi zrzutami
Dane, o które zapytanie zostało wysłane w fazie SSR, są przydatne do początkowego renderowania po stronie klienta, ale nadal może być konieczne monitorowanie usługi Firestore pod kątem aktualizacji tych informacji w czasie rzeczywistym.
Jeśli Twoja aplikacja wymaga tych aktualizacji w czasie rzeczywistym, możesz użyć funkcji onSnapshotResume
do inicjowania Firestore SnapshotListenerz serializowanymi Snapshot
danymi. Przykład:
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);