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

Le app che utilizzano qualsiasi API web Firebase con spazio dei nomi, dalle librerie compat fino alla versione 8 o precedenti, devono prendere in considerazione la migrazione all'API modulare seguendo le istruzioni riportate in questa guida.

Questa guida presuppone che tu conosca l'API con spazi dei nomi e che utilizzerai un bundler di moduli come webpack o Rollup per l'upgrade e lo sviluppo modulare continuo di app.

L'utilizzo di un bundler di moduli nell'ambiente di sviluppo è vivamente consigliato. Se non ne utilizzi uno, non potrai usufruire dei principali vantaggi dell'API modulare in termini di riduzione delle dimensioni dell'app. Per installare l'SDK, devi utilizzare npm o yarn.

I passaggi di upgrade descritti in questa guida si baseranno su un'app web immaginaria che utilizza gli SDK Authentication e Cloud Firestore. Se esamini gli esempi, puoi padroneggiare i concetti e i passaggi pratici necessari per eseguire l'upgrade di tutti gli SDK web Firebase supportati.

Informazioni sulle librerie con spazio dei nomi (compat)

Esistono due tipi di librerie disponibili per l'SDK web di Firebase:

  • Modulare: una nuova superficie API progettata per facilitare l'eliminazione del codice inutilizzato per rendere la tua app web il più piccola e veloce possibile.
  • Con spazio dei nomi (compat): una superficie API familiare completamente compatibile con le versioni precedenti dell'SDK, che ti consente di eseguire l'upgrade senza modificare tutto il codice Firebase contemporaneamente. Le librerie di compatibilità non offrono vantaggi in termini di dimensioni o prestazioni rispetto alle controparti con spazio dei nomi.

Questa guida presuppone che tu utilizzi le librerie di compatibilità per facilitare l'upgrade. Queste librerie ti consentono di continuare a utilizzare il codice con spazi 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 mentre procedi con l'upgrade.

Per le app con un'esposizione molto ridotta all'SDK web Firebase, ad esempio un'app che effettua solo una semplice chiamata alle API Authentication, potrebbe essere pratico eseguire il refactoring del codice con spazi dei nomi precedenti senza utilizzare le librerie compat. Se stai eseguendo l'upgrade di un'app di questo tipo, puoi seguire le istruzioni riportate in questa guida per "l'API modulare" senza utilizzare le librerie di compatibilità.

Informazioni sulla procedura di upgrade

Ogni passaggio della procedura di upgrade è definito in modo da poter terminare la modifica del codice sorgente dell'app, quindi compilarlo ed eseguirlo senza interruzioni. In sintesi, ecco cosa devi fare per eseguire l'upgrade di un'app:

  1. Aggiungi le librerie modulari e le librerie compat alla tua app.
  2. Aggiorna le istruzioni di importazione nel codice per la compatibilità.
  3. Refactorizza il codice per un singolo prodotto (ad esempio Authentication) nello stile modulare.
  4. (Facoltativo) A questo punto, rimuovi la libreria di compatibilità Authentication e il codice di compatibilità per Authentication per ottenere il vantaggio di dimensioni dell'app per Authentication prima di continuare.
  5. Refactorizza le funzioni per ogni prodotto (ad esempio, Cloud Firestore, FCM e così via) nello 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 di compatibilità e il codice di compatibilità rimanenti dalla tua app.

Scarica l'ultima versione dell'SDK

Per iniziare, scarica le librerie modulari e di compatibilità utilizzando npm:

npm i firebase@12.0.0

# OR

yarn add firebase@12.0.0

Aggiornare le importazioni alla compatibilità

Per mantenere il funzionamento del codice dopo l'aggiornamento delle dipendenze, modifica le istruzioni di importazione in modo che utilizzino la versione "compat" di ogni importazione. Ad 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';

Esegui il refactoring allo stile modulare

Mentre le API con spazio dei nomi si basano su un pattern di spazio dei nomi e servizio concatenato con un punto, l'approccio modulare prevede che il codice sia organizzato principalmente intorno 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 i dettagli del servizio per fare il resto. Esaminiamo come funziona in due esempi che eseguono il refactoring delle chiamate alle API Authentication e Cloud Firestore.

Esempio 1: refactoring di una funzione Authentication

Prima: compat

Il codice di compatibilità è 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 nell'API con spazio dei nomi. Si tratta invece di una funzione libera che accetta auth come primo parametro.

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

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

Aggiorna la gestione del metodo di autenticazione getRedirectResult

L'API modulare introduce una modifica che causa interruzioni in getRedirectResult. Quando non viene chiamata alcuna operazione di reindirizzamento, l'API modulare restituisce null anziché l'API con spazio dei nomi, che restituiva un 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, che è stato restituito da initializeApp in un esempio precedente. Tieni presente che il codice per formare una query è molto diverso nell'API modulare: non esiste concatenazione e metodi come query o where sono ora esposti come funzioni senza costi.

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 incompatibile in cui la proprietà firestore.DocumentSnapshot.exists è stata modificata in un metodo. La funzionalità è essenzialmente la stessa (verifica se esiste un documento), ma devi eseguire il refactoring del codice per utilizzare il metodo più recente come mostrato di seguito:

Prima:compat

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 spazi dei nomi e modulari

L'utilizzo delle librerie di compatibilità durante l'upgrade ti consente di continuare a utilizzare il codice con spazi dei nomi insieme al codice sottoposto a refactoring per l'API modulare. Ciò significa che puoi conservare il codice con spazi dei nomi esistente per Cloud Firestore mentre esegui il refactoring di Authentication o di altro codice SDK Firebase nello stile modulare e compilare comunque correttamente l'app con entrambi gli stili di codice. Lo stesso vale per il codice API modulare e con spazi dei nomi all'interno di un prodotto come Cloud Firestore; gli stili di codice nuovi e precedenti possono coesistere, a condizione che tu importi i pacchetti di compatibilità:

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 delle dimensioni dell'app del codice modulare finché non rimuoverai completamente le istruzioni di compatibilità e il codice dalla tua app.

Aggiornare il codice di inizializzazione

Aggiorna il codice di inizializzazione dell'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 le API compat che per quelle modulari, mentre la funzione initializeApp() inizializza solo lo stato per le API modulari.

Prima: compat

import firebase from "firebase/compat/app"

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

Dopo: modulare

import { initializeApp } from "firebase/app"

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

Rimuovi codice di compatibilità

Per sfruttare i vantaggi in termini di dimensioni dell'API modulare, alla fine devi convertire tutte le chiamate allo stile modulare mostrato sopra e rimuovere tutte le istruzioni import "firebase/compat/* dal codice. Al termine, non dovrebbero esserci più riferimenti allo spazio dei nomi globale firebase.* o ad altro codice nello stile API con spazio dei nomi.

Utilizzo della libreria di compatibilità 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. In futuro non è consigliato perché non consente l'eliminazione del codice inutilizzato. Tuttavia, la versione compatibile dell'SDK JavaScript funziona con window per gli sviluppatori che preferiscono non iniziare immediatamente il percorso di upgrade modulare.

<script src="https://www.gstatic.com/firebasejs/12.0.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.0.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.0.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 e lo fornisce con la stessa API dell'API con spazio dei nomi; ciò significa che puoi fare riferimento alla documentazione di riferimento dell'API con spazio dei nomi e agli snippet di codice con spazio dei nomi per i dettagli. Questo metodo non è consigliato per l'uso a lungo termine, ma come punto di partenza per l'upgrade alla libreria completamente modulare.

Vantaggi e limitazioni dell'SDK modulare

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

  • L'SDK modulare consente di ridurre drasticamente le dimensioni dell'app. Adotta il formato moderno dei moduli JavaScript, consentendo pratiche di "tree shaking" in cui importi solo gli artefatti necessari alla tua app. A seconda dell'app, l'eliminazione del codice inutilizzato con l'SDK modulare può comportare una riduzione dell'80% dei kilobyte rispetto a un'app comparabile creata utilizzando l'API con spazio dei nomi.
  • L'SDK modulare continuerà a beneficiare dello sviluppo continuo di funzionalità, mentre l'API con spazio dei nomi non lo farà.