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 abbia familiarità con l'API con spazio dei nomi e che utilizzerai un bundler di moduli come webpack o Rollup per l'upgrade e lo sviluppo continuo di app modulari.

Ti consigliamo vivamente di utilizzare un bundler di moduli nel tuo ambiente di sviluppo. Se non ne utilizzi uno, non potrai sfruttare i principali vantaggi dell'API modulare in termini di riduzione delle dimensioni dell'app. Per installare l'SDK, devi avere 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. Lavorando sugli esempi, puoi acquisire familiarità con 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)

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

  • Modulare : una nuova superficie API progettata per facilitare l'eliminazione del codice inutilizzato (tree-shaking) al fine di 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 immediatamente tutto il codice Firebase. Le librerie di compatibilità offrono vantaggi di dimensioni o prestazioni minimi o nulli rispetto alle controparti con spazio dei nomi.

Questa guida presuppone che utilizzerai le librerie di compatibilità per facilitare l'upgrade. 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 dell'app più facilmente durante la procedura di 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 spazio dei nomi precedente senza utilizzare le librerie di compatibilità. 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 è limitato in modo che tu possa completare la modifica dell'origine dell'app, quindi compilarla ed eseguirla senza interruzioni. In sintesi, ecco cosa devi fare per eseguire l'upgrade di un'app:

  1. Aggiungi le librerie modulari e le librerie di compatibilità all'app.
  2. Aggiorna le istruzioni di importazione nel codice alla compatibilità.
  3. Esegui il refactoring del codice per un singolo prodotto (ad esempio Authentication) in 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. Esegui il refactoring delle funzioni per ogni prodotto (ad esempio, Cloud Firestore, FCM, e così via) in stile modulare, compilando ed eseguendo i test finché tutte le aree non sono complete.
  6. Aggiorna il codice di inizializzazione in stile modulare.
  7. Rimuovi tutte le istruzioni di compatibilità e il codice di compatibilità rimanenti da ll'app.

Scarica l'ultima versione dell'SDK

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

npm i firebase@12.10.0

# OR

yarn add firebase@12.10.0

Aggiorna le importazioni alla compatibilità

Per mantenere il funzionamento del codice dopo l'aggiornamento delle dipendenze, modifica le istruzioni di importazione in modo da utilizzare la versione "compat" di ogni importazione. Ad esempio:

Prima: versione 8 o precedenti

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

Dopo: compatibilità

// 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 in stile modulare

Mentre le API con spazio dei nomi si basano su un pattern di spazio dei nomi e servizi con concatenazione di punti, 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 contiene tutti i metodi del pacchetto. Al contrario, i pacchetti esportano singole funzioni.

Nell'API modulare, i servizi vengono passati come primo argomento e la funzione quindi utilizza i dettagli del servizio per 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: compatibilità

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 onAuthStateChanged funzione non è concatenata dall'istanza auth come sarebbe nell'API con spazio dei nomi; al contrario, è 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 Auth getRedirectResult

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

Prima: compatibilità

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 Cloud Firestore funzione

Prima: compatibilità

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 la concatenazione 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 che causa un'interruzione 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:compatibilità

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 di compatibilità durante l'upgrade ti 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 del codice di Authentication o di altri SDK Firebase in stile modulare e compilare comunque l'app con entrambi gli stili di codice. Lo stesso vale per il codice API con spazio dei nomi e modulare all'interno di un prodotto come Cloud Firestore; i nuovi e i vecchi stili di codice possono coesistere, a condizione che tu stia importando 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 l'app verrà compilata, non otterrai i vantaggi di dimensioni dell'app del codice modulare finché non rimuovi completamente le istruzioni e il codice di compatibilità dall'app.

Aggiorna il codice di inizializzazione

Aggiorna il codice di inizializzazione dell'app in modo da utilizzare la sintassi modulare. È importante aggiornare questo codice dopo aver completato il refactoring di tutto il codice dell'app, perché firebase.initializeApp() inizializza lo stato globale sia per le API di compatibilità sia per le API modulari, mentre la funzione initializeApp() modulare inizializza solo lo stato per le API modulari.

Prima: compatibilità

import firebase from "firebase/compat/app"

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

Dopo: modulare

import { initializeApp } from "firebase/app"

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

Rimuovi il codice di compatibilità

Per ottenere i vantaggi di dimensioni dell'API modulare, devi eventualmente convertire tutte le invocazioni in stile modulare come mostrato sopra e rimuovere tutte le import "firebase/compat/* istruzioni dal codice. Al termine, non dovrebbero essere presenti altri riferimenti allo spazio dei nomi globale firebase.* o ad altro codice nello stile dell'API con spazio dei nomi.

Utilizza la 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. Questo approccio non è consigliato per il futuro, in quanto non consente l'eliminazione del codice inutilizzato. Tuttavia, la versione di compatibilità 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.10.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.10.0/firebase-firestore-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/12.10.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 il codice modulare sottostante 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 modularizzato presenta i seguenti vantaggi rispetto alle versioni precedenti:

  • L'SDK modulare consente di ridurre drasticamente le dimensioni dell'app. Adotta il formato del modulo JavaScript moderno, consentendo pratiche di "tree-shaking" in cui importi solo gli artefatti di cui la tua app ha bisogno. A seconda dell'app, il tree-shaking con l'SDK modulare può comportare una riduzione dei kilobyte dell'80% rispetto a un' app comparabile creata utilizzando l'API con spazio dei nomi.
  • L'SDK modulare continuerà a beneficiare dello sviluppo continuo delle funzionalità, mentre l'API con spazio dei nomi no.