Uaktualnij interfejs API z przestrzenią nazw do modułowego interfejsu API

Aplikacje korzystające obecnie z dowolnego interfejsu API Firebase Web API z compat nazw, z bibliotek zgodnych aż do wersji 8 lub wcześniejszej, powinny rozważyć migrację do modułowego interfejsu API, korzystając z instrukcji zawartych w tym przewodniku.

W tym przewodniku założono, że znasz interfejs API z przestrzenią nazw i że będziesz korzystać z pakietu modułów, takiego jak pakiet internetowy lub pakiet zbiorczy , do aktualizacji i ciągłego tworzenia aplikacji modułowych.

Zdecydowanie zaleca się używanie pakietu modułów w środowisku programistycznym. Jeśli go nie użyjesz, nie będziesz mógł skorzystać z głównych zalet modułowego API w postaci zmniejszonego rozmiaru aplikacji. Aby zainstalować zestaw SDK, będziesz potrzebować npm lub przędzy .

Kroki aktualizacji opisane w tym przewodniku będą oparte na wyimaginowanej aplikacji internetowej korzystającej z zestawów SDK uwierzytelniania i Cloud Firestore. Pracując nad przykładami, możesz opanować koncepcje i praktyczne kroki wymagane do uaktualnienia wszystkich obsługiwanych zestawów SDK Firebase Web.

Informacje o bibliotekach z przestrzenią nazw ( compat ).

Dla pakietu Firebase Web SDK dostępne są dwa typy bibliotek:

  • Modular - nowa powierzchnia API zaprojektowana w celu ułatwienia potrząsania drzewem (usuwania nieużywanego kodu), aby Twoja aplikacja internetowa była jak mała i szybka.
  • Namespaced ( compat ) - znana powierzchnia API, która jest w pełni kompatybilna z wcześniejszymi wersjami pakietu SDK, umożliwiając aktualizację bez zmiany całego kodu Firebase na raz. Biblioteki kompatybilne mają niewielką lub żadną przewagę pod względem rozmiaru i wydajności w porównaniu z ich odpowiednikami w przestrzeni nazw.

W tym przewodniku założono, że skorzystasz z kompatybilnych bibliotek, aby ułatwić aktualizację. Biblioteki te umożliwiają dalsze używanie kodu z przestrzenią nazw wraz z kodem refaktoryzowanym dla modułowego interfejsu API. Oznacza to, że możesz łatwiej kompilować i debugować aplikację podczas procesu aktualizacji.

W przypadku aplikacji z bardzo małym dostępem do pakietu Firebase Web SDK — na przykład aplikacji, która wykonuje jedynie proste wywołanie interfejsów API uwierzytelniania — praktyczne może być refaktoryzacja starszego kodu z przestrzenią nazw bez korzystania ze zgodnych bibliotek. Jeśli aktualizujesz taką aplikację, możesz postępować zgodnie z instrukcjami zawartymi w tym przewodniku dotyczącymi „modułowego interfejsu API” bez korzystania z kompatybilnych bibliotek.

Informacje o procesie aktualizacji

Każdy etap procesu aktualizacji ma taki zakres, że można zakończyć edycję źródła aplikacji, a następnie skompilować ją i uruchomić bez uszkodzeń. Podsumowując, oto czynności, które należy wykonać, aby zaktualizować aplikację:

  1. Dodaj biblioteki modułowe i biblioteki kompatybilne do swojej aplikacji.
  2. Zaktualizuj instrukcje importu w swoim kodzie do zgodności.
  3. Zmień kod pojedynczego produktu (na przykład Uwierzytelnianie) na styl modułowy.
  4. Opcjonalnie: w tym momencie usuń bibliotekę zgodności uwierzytelniania i kod zgodności uwierzytelniania, aby przed kontynuowaniem skorzystać z korzyści związanych z rozmiarem aplikacji w zakresie uwierzytelniania.
  5. Refaktoryzuj funkcje dla każdego produktu (na przykład Cloud Firestore, FCM itp.) do stylu modułowego, kompilując i testując, aż wszystkie obszary zostaną ukończone.
  6. Zaktualizuj kod inicjujący do stylu modułowego.
  7. Usuń wszystkie pozostałe instrukcje dotyczące zgodności i kod zgodności ze swojej aplikacji.

Pobierz najnowszą wersję pakietu SDK

Aby rozpocząć, pobierz biblioteki modułowe i biblioteki kompatybilne za pomocą npm:

npm i firebase@10.9.0

# OR

yarn add firebase@10.9.0

Zaktualizuj import do zgodności

Aby kod nadal działał po zaktualizowaniu zależności, zmień instrukcje importu, aby korzystały z „kompatybilnej” wersji każdego importu. Na przykład:

Wcześniej: wersja 8 lub wcześniejsza

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

Po: zgodny

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

Refaktoryzuj do stylu modułowego

Chociaż interfejsy API z przestrzenią nazw opierają się na przestrzeni nazw i wzorcu usług z łańcuchami kropkowymi, podejście modułowe oznacza, że ​​kod będzie zorganizowany głównie wokół funkcji . W modułowym API pakiet firebase/app i inne pakiety nie zwracają kompleksowego eksportu zawierającego wszystkie metody z pakietu. Zamiast tego pakiety eksportują poszczególne funkcje.

W modułowym API usługi są przekazywane jako pierwszy argument, a funkcja następnie wykorzystuje szczegóły usługi, aby zrobić resztę. Przeanalizujmy, jak to działa na dwóch przykładach, które refaktoryzują wywołania interfejsów API Authentication i Cloud Firestore.

Przykład 1: refaktoryzacja funkcji uwierzytelniania

Przed: zgodność

Kod zgodności jest identyczny z kodem z przestrzenią nazw, ale import uległ zmianie.

import firebase from "firebase/compat/app";
import "firebase/compat/auth";

const auth = firebase.auth();
auth.onAuthStateChanged(user => { 
  // Check for user status
});

Po: modułowy

Funkcja getAuth przyjmuje firebaseApp jako swój pierwszy parametr. Funkcja onAuthStateChanged nie jest połączona z instancją auth , jak miałoby to miejsce w interfejsie API z przestrzenią nazw; zamiast tego jest to darmowa funkcja, której pierwszym parametrem jest auth .

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

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

Aktualizacja obsługi metody uwierzytelniania getRedirectResult

Modułowe API wprowadza przełomową zmianę w getRedirectResult . Gdy nie zostanie wywołana żadna operacja przekierowania, modułowy interfejs API zwraca null w przeciwieństwie do interfejsu API z przestrzenią nazw, który zwrócił UserCredential z użytkownikiem null .

Przed: zgodność

const result = await auth.getRedirectResult()
if (result.user === null && result.credential === null) {
  return null;
}
return result;

Po: modułowy

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;

Przykład 2: refaktoryzacja funkcji Cloud Firestore

Przed: zgodność

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);
    });

Po: modułowe

Funkcja getFirestore przyjmuje firebaseApp jako swój pierwszy parametr, który został zwrócony przez initializeApp we wcześniejszym przykładzie. Zwróć uwagę, że kod służący do tworzenia zapytania różni się znacznie w modułowym interfejsie API; nie ma żadnego łączenia, a metody takie jak query lub where są teraz dostępne jako darmowe funkcje.

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());
});

Zaktualizuj odniesienia do pliku Firestore DocumentSnapshot.exists

Modułowe API wprowadza istotną zmianę, w której właściwość firestore.DocumentSnapshot.exists została zmieniona na metodę . Funkcjonalność jest zasadniczo taka sama (testowanie, czy dokument istnieje), ale musisz dokonać refaktoryzacji kodu, aby użyć nowszej metody, jak pokazano:

Przed: zgodność

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

Po: modułowe

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

Przykład 3: łączenie stylów kodu z przestrzenią nazw i modułowych

Korzystanie z kompatybilnych bibliotek podczas aktualizacji umożliwia dalsze używanie kodu z przestrzenią nazw wraz z kodem refaktoryzowanym dla modułowego interfejsu API. Oznacza to, że możesz zachować istniejący kod z przestrzenią nazw dla Cloud Firestore podczas refaktoryzacji uwierzytelniania lub innego kodu pakietu SDK Firebase do stylu modułowego i nadal pomyślnie kompilować aplikację przy użyciu obu stylów kodu. To samo dotyczy modułowego kodu API z przestrzenią nazw w produkcie takim jak Cloud Firestore; nowe i stare style kodu mogą współistnieć, o ile importujesz pakiety kompatybilne:

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

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

Pamiętaj, że chociaż Twoja aplikacja zostanie skompilowana, nie uzyskasz korzyści wynikających z rozmiaru aplikacji wynikającego z kodu modułowego, dopóki całkowicie nie usuniesz instrukcji zgodności i kodu z aplikacji.

Zaktualizuj kod inicjujący

Zaktualizuj kod inicjujący aplikacji, aby używać składni modułowej. Ważne jest, aby zaktualizować ten kod po zakończeniu refaktoryzacji całego kodu w aplikacji; dzieje się tak, ponieważ firebase.initializeApp() inicjuje stan globalny zarówno dla interfejsów API zgodnych, jak i modułowych, podczas gdy funkcja modularna initializeApp() inicjuje tylko stan modułowy.

Przed: zgodność

import firebase from "firebase/compat/app"

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

Po: modułowe

import { initializeApp } from "firebase/app"

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

Usuń kod zgodności

Aby skorzystać z zalet modułowego API w zakresie rozmiaru, powinieneś ostatecznie przekonwertować wszystkie wywołania na styl modułowy pokazany powyżej i usunąć wszystkie instrukcje import "firebase/compat/* ze swojego kodu. Kiedy skończysz, nie powinno być już żadnych odniesień do globalnej przestrzeni nazw firebase.* lub dowolnego innego kodu w stylu API z przestrzenią nazw.

Korzystanie z biblioteki compat z poziomu okna

Modułowy interfejs API jest zoptymalizowany do pracy z modułami, a nie z obiektem window przeglądarki. Poprzednie wersje biblioteki umożliwiały ładowanie Firebase i zarządzanie nim przy użyciu przestrzeni nazw window.firebase . Nie jest to zalecane w przyszłości, ponieważ nie pozwala na eliminację nieużywanego kodu. Jednak zgodna wersja pakietu JavaScript SDK współpracuje z window dla programistów, którzy wolą nie rozpoczynać od razu modułowej ścieżki aktualizacji.

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

Biblioteka kompatybilności wykorzystuje pod maską kod modułowy i udostępnia mu ten sam interfejs API, co interfejs API z przestrzenią nazw; oznacza to, że szczegółowe informacje można znaleźć w dokumentacji API z przestrzenią nazw i fragmentach kodu z przestrzenią nazw. Ta metoda nie jest zalecana do długotrwałego stosowania, ale jako początek aktualizacji do w pełni modułowej biblioteki.

Korzyści i ograniczenia modułowego SDK

W pełni modułowy zestaw SDK ma następujące zalety w porównaniu z wcześniejszymi wersjami:

  • Modułowy pakiet SDK umożliwia radykalne zmniejszenie rozmiaru aplikacji. Przyjmuje nowoczesny format modułu JavaScript, umożliwiając praktyki „potrząsania drzewem”, w ramach których importujesz tylko te artefakty, których potrzebuje Twoja aplikacja. W zależności od aplikacji wstrząsanie drzewem za pomocą modułowego zestawu SDK może skutkować o 80% mniej kilobajtów niż porównywalna aplikacja zbudowana przy użyciu interfejsu API z przestrzenią nazw.
  • Modułowy zestaw SDK będzie nadal czerpał korzyści z ciągłego rozwoju funkcji, podczas gdy interfejs API z przestrzenią nazw nie.