Esegui l'upgrade dall'API con spazio dei nomi all'API modulare

Le app che attualmente utilizzano qualsiasi API Web Firebase con spazio dei nomi, dalle librerie compat fino alla versione 8 o precedente, dovrebbero prendere in considerazione la migrazione all'API modulare utilizzando le istruzioni contenute in questa guida.

Questa guida presuppone che tu abbia familiarità con l'API con spazio dei nomi e che trarrai vantaggio da un bundler di moduli come webpack o Rollup per l'aggiornamento e lo sviluppo continuo di app modulari.

Si consiglia vivamente di utilizzare un bundler di moduli nel proprio ambiente di sviluppo. Se non ne usi uno, non sarai in grado di sfruttare i principali vantaggi dell'API modulare in termini di dimensioni ridotte dell'app. Avrai bisogno di npm o Yarn per installare l'SDK.

I passaggi di aggiornamento descritti in questa guida si baseranno su un'app Web immaginaria che utilizza gli SDK di autenticazione e Cloud Firestore. Analizzando gli esempi, puoi padroneggiare i concetti e i passaggi pratici necessari per aggiornare tutti gli SDK Web Firebase supportati.

Informazioni sulle librerie con spazi dei nomi ( compat ).

Sono disponibili due tipi di librerie per Firebase Web SDK:

  • Modulare : una nuova superficie API progettata per facilitare il tree-shaking (rimozione del codice inutilizzato) per rendere la tua app Web il più piccola e veloce possibile.
  • Namespaced ( compat ) : una superficie API familiare completamente compatibile con le versioni precedenti dell'SDK, che ti consente di eseguire l'aggiornamento senza modificare tutto il codice Firebase contemporaneamente. Le librerie compat presentano vantaggi minimi o nulli in termini di dimensioni o prestazioni rispetto alle loro controparti con spazio dei nomi.

Questa guida presuppone che utilizzerai le librerie compatibili per facilitare l'aggiornamento. Queste librerie ti consentono di continuare a utilizzare il codice con spazio dei nomi insieme al codice sottoposto a refactoring per l'API modulare. Ciò significa che puoi compilare ed eseguire il debug della tua app più facilmente durante il processo di aggiornamento.

Per le app con un'esposizione molto ridotta all'SDK Web Firebase, ad esempio un'app che effettua solo una semplice chiamata alle API di autenticazione, potrebbe essere pratico eseguire il refactoring del codice con spazio dei nomi precedente senza utilizzare le librerie compat. Se stai aggiornando un'app di questo tipo, puoi seguire le istruzioni in questa guida per "l'API modulare" senza utilizzare le librerie compat.

Informazioni sul processo di aggiornamento

Ogni passaggio del processo di aggiornamento ha un ambito tale da consentirti di completare la modifica dell'origine della tua app e quindi compilarla ed eseguirla senza interruzioni. In sintesi, ecco cosa farai per aggiornare un'app:

  1. Aggiungi le librerie modulari e le librerie compat alla tua app.
  2. Aggiorna le istruzioni di importazione nel tuo codice per compat.
  3. Codice di refactoring per un singolo prodotto (ad esempio, Autenticazione) nello stile modulare.
  4. Facoltativo: a questo punto, rimuovere la libreria compat di autenticazione e il codice compat per l'autenticazione per ottenere il vantaggio in termini di dimensioni dell'app per l'autenticazione prima di continuare.
  5. Funzioni di refactoring per ciascun prodotto (ad esempio, Cloud Firestore, FCM, ecc.) in stile modulare, compilando e testando fino al completamento di tutte le aree.
  6. Aggiorna il codice di inizializzazione allo stile modulare.
  7. Rimuovi tutte le istruzioni compat e il codice compat rimanenti dalla tua app.

Ottieni la versione più recente dell'SDK

Per iniziare, scarica le librerie modulari e le librerie compat utilizzando npm:

npm i firebase@10.9.0

# OR

yarn add firebase@10.9.0

Aggiorna le importazioni alla compatibilità

Per mantenere il codice funzionante dopo aver aggiornato le dipendenze, modifica le istruzioni di importazione per utilizzare la versione "compat" di ciascuna importazione. Per esempio:

Prima: versione 8 o precedente

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

Dopo: compat

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

Refactoring in stile modulare

Sebbene le API con spazio dei nomi siano basate su uno spazio dei nomi e un modello di servizio concatenati a punti, l'approccio modulare significa che il codice sarà organizzato principalmente attorno alle funzioni . Nell'API modulare, il pacchetto firebase/app e altri pacchetti non restituiscono un'esportazione completa che contenga tutti i metodi del pacchetto. I pacchetti esportano invece singole funzioni.

Nell'API modulare, i servizi vengono passati come primo argomento e la funzione utilizza quindi i dettagli del servizio per fare il resto. Esaminiamo come funziona in due esempi di refactoring delle chiamate alle API Authentication e Cloud Firestore.

Esempio 1: refactoring di una funzione di autenticazione

Prima: compat

Il codice compat è identico al codice con spazio dei nomi, ma le importazioni sono cambiate.

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

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

Dopo: modulare

La funzione getAuth accetta firebaseApp come primo parametro. La funzione onAuthStateChanged non è concatenata dall'istanza auth come sarebbe nell'API con spazio dei nomi; invece, è una funzione gratuita che accetta auth come primo parametro.

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

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

Gestione degli aggiornamenti del metodo Auth getRedirectResult

L'API modulare introduce una modifica sostanziale in getRedirectResult . Quando non viene chiamata alcuna operazione di reindirizzamento, l'API modulare restituisce null al contrario dell'API con spazio dei nomi, che restituiva una UserCredential con un utente null .

Prima: compat

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

Dopo: modulare

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;

Esempio 2: refactoring di una funzione Cloud Firestore

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

Dopo: modulare

La funzione getFirestore accetta firebaseApp come primo parametro, restituito da initializeApp in un esempio precedente. Nota come il codice per formare una query è molto diverso nell'API modulare; non è previsto alcun concatenamento e metodi come query o where sono ora esposti come funzioni libere.

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

Aggiorna i riferimenti a Firestore DocumentSnapshot.exists

L'API modulare introduce una modifica sostanziale in cui la proprietà firestore.DocumentSnapshot.exists è stata modificata in un metodo . La funzionalità è essenzialmente la stessa (testare se un documento esiste) ma è necessario effettuare il refactoring del codice per utilizzare il metodo più recente come mostrato:

Prima:comp

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

Dopo: modulare

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

Esempio 3: combinazione di stili di codice con spazio dei nomi e modulari

L'utilizzo delle librerie compat durante l'aggiornamento consente di continuare a utilizzare il codice con spazio dei nomi insieme al codice sottoposto a refactoring per l'API modulare. Ciò significa che puoi mantenere il codice con spazio dei nomi esistente per Cloud Firestore mentre esegui il refactoring dell'autenticazione o di altro codice SDK Firebase nello stile modulare e comunque compilare correttamente la tua app con entrambi gli stili di codice. Lo stesso vale per il codice API modulare e con spazio dei nomi all'interno di un prodotto come Cloud Firestore; gli stili di codice nuovi e vecchi possono coesistere, purché si importino i pacchetti compat:

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

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

Tieni presente che, anche se la tua app verrà compilata, non otterrai i vantaggi in termini di dimensioni dell'app derivanti dal codice modulare finché non rimuoverai completamente le istruzioni compat e il codice dalla tua app.

Aggiorna il codice di inizializzazione

Aggiorna il codice di inizializzazione della tua app per utilizzare la sintassi modulare. È importante aggiornare questo codice dopo aver completato il refactoring di tutto il codice nell'app; questo perché firebase.initializeApp() inizializza lo stato globale sia per l'API compat che per quella modulare, mentre la funzione modular initializeApp() inizializza solo lo stato per modular.

Prima: compat

import firebase from "firebase/compat/app"

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

Dopo: modulare

import { initializeApp } from "firebase/app"

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

Rimuovi il codice compatibile

Per realizzare i vantaggi in termini di dimensioni dell'API modulare, dovresti eventualmente convertire tutte le invocazioni nello stile modulare mostrato sopra e rimuovere tutte le istruzioni import "firebase/compat/* dal tuo codice. Una volta terminato, non dovrebbero esserci più riferimenti allo spazio dei nomi globale firebase.* o qualsiasi altro codice nello stile API con spazio dei nomi.

Utilizzando la libreria compat dalla finestra

L'API modulare è ottimizzata per funzionare con i moduli anziché con l'oggetto window del browser. Le versioni precedenti della libreria consentivano il caricamento e la gestione di Firebase utilizzando lo spazio dei nomi window.firebase . Questa operazione non è consigliata in futuro poiché non consente l'eliminazione del codice inutilizzato. Tuttavia, la versione compatibile dell'SDK JavaScript funziona con la window per gli sviluppatori che preferiscono non iniziare immediatamente il percorso di aggiornamento modulare.

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

La libreria di compatibilità utilizza codice modulare dietro le quinte e fornisce la stessa API dell'API con spazio dei nomi; ciò significa che puoi fare riferimento al riferimento API con spazio dei nomi e agli snippet di codice con spazio dei nomi per i dettagli. Questo metodo non è consigliato per un utilizzo a lungo termine, ma come inizio per l'aggiornamento alla libreria completamente modulare.

Vantaggi e limiti dell'SDK modulare

L'SDK completamente modulare presenta questi vantaggi rispetto alle versioni precedenti:

  • L'SDK modulare consente di ridurre notevolmente le dimensioni dell'app. Adotta il moderno formato del modulo JavaScript, consentendo pratiche di "scuotimento degli alberi" in cui importi solo gli artefatti necessari alla tua app. A seconda dell'app, lo scuotimento degli alberi con l'SDK modulare può comportare l'80% di kilobyte in meno rispetto a un'app comparabile creata utilizzando l'API con spazio dei nomi.
  • L'SDK modulare continuerà a trarre vantaggio dallo sviluppo continuo delle funzionalità, mentre l'API con spazio dei nomi no.