Actualice de la API con espacio de nombres a la API modular

Las aplicaciones que actualmente utilizan cualquier API web de Firebase con espacio de nombres, desde las bibliotecas compat hasta la versión 8 o anterior, deberían considerar migrar a la API modular siguiendo las instrucciones de esta guía.

Esta guía supone que está familiarizado con la API de espacio de nombres y que aprovechará un paquete de módulos como webpack o Rollup para actualizar y desarrollar aplicaciones modulares continuas.

Se recomienda encarecidamente utilizar un paquete de módulos en su entorno de desarrollo. Si no utiliza una, no podrá aprovechar los principales beneficios de la API modular en el tamaño reducido de la aplicación. Necesitará npm o hilo para instalar el SDK.

Los pasos de actualización de esta guía se basarán en una aplicación web imaginaria que utiliza los SDK de autenticación y Cloud Firestore. Al trabajar con los ejemplos, podrá dominar los conceptos y los pasos prácticos necesarios para actualizar todos los SDK web de Firebase compatibles.

Acerca de las bibliotecas con espacios de nombres ( compat )

Hay dos tipos de bibliotecas disponibles para Firebase Web SDK:

  • Modular : una nueva superficie API diseñada para facilitar la agitación de árboles (eliminación de código no utilizado) para que su aplicación web sea lo más pequeña y rápida posible.
  • Namespaced ( compat ) : una superficie API familiar que es totalmente compatible con las versiones anteriores del SDK, lo que le permite actualizar sin cambiar todo el código de Firebase a la vez. Las bibliotecas de compatibilidad tienen pocas o ninguna ventaja de tamaño o rendimiento sobre sus contrapartes con espacios de nombres.

Esta guía asume que aprovechará las bibliotecas compatibles para facilitar su actualización. Estas bibliotecas le permiten continuar usando código con espacio de nombres junto con código refactorizado para la API modular. Esto significa que puede compilar y depurar su aplicación más fácilmente a medida que avanza en el proceso de actualización.

Para aplicaciones con una exposición muy pequeña al SDK web de Firebase (por ejemplo, una aplicación que solo realiza una simple llamada a las API de autenticación), puede resultar práctico refactorizar el código de espacio de nombres anterior sin utilizar las bibliotecas de compatibilidad. Si está actualizando una aplicación de este tipo, puede seguir las instrucciones de esta guía para "la API modular" sin utilizar las bibliotecas de compatibilidad.

Acerca del proceso de actualización

Cada paso del proceso de actualización tiene como objetivo que pueda terminar de editar el código fuente de su aplicación y luego compilarla y ejecutarla sin interrupciones. En resumen, esto es lo que deberá hacer para actualizar una aplicación:

  1. Agregue las bibliotecas modulares y las bibliotecas compatibles a su aplicación.
  2. Actualice las declaraciones de importación en su código para que sean compatibles.
  3. Refactorice el código para un solo producto (por ejemplo, Autenticación) al estilo modular.
  4. Opcional: en este punto, elimine la biblioteca de compatibilidad de autenticación y el código de compatibilidad de autenticación para obtener el beneficio del tamaño de la aplicación para la autenticación antes de continuar.
  5. Refactorice las funciones para cada producto (por ejemplo, Cloud Firestore, FCM, etc.) al estilo modular, compilando y probando hasta que todas las áreas estén completas.
  6. Actualice el código de inicialización al estilo modular.
  7. Elimine todas las declaraciones de compatibilidad restantes y el código de compatibilidad de su aplicación.

Obtenga la última versión del SDK

Para comenzar, obtenga las bibliotecas modulares y las bibliotecas compatibles usando npm:

npm i firebase@10.9.0

# OR

yarn add firebase@10.9.0

Actualizar importaciones para que sean compatibles

Para mantener su código funcionando después de actualizar sus dependencias, cambie sus declaraciones de importación para usar la versión "compatible" de cada importación. Por ejemplo:

Antes: versión 8 o anterior

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

Después: compatible

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

Refactorizar al estilo modular

Si bien las API con espacios de nombres se basan en un patrón de servicio y espacio de nombres con cadena de puntos, el enfoque modular significa que su código se organizará principalmente en torno a funciones . En la API modular, el paquete firebase/app y otros paquetes no devuelven una exportación completa que contenga todos los métodos del paquete. En cambio, los paquetes exportan funciones individuales.

En la API modular, los servicios se pasan como primer argumento y luego la función utiliza los detalles del servicio para hacer el resto. Examinemos cómo funciona esto en dos ejemplos que refactorizan las llamadas a las API de autenticación y Cloud Firestore.

Ejemplo 1: refactorizar una función de autenticación

Antes: compatible

El código de compatibilidad es idéntico al código de espacio de nombres, pero las importaciones han cambiado.

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

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

Después: modular

La función getAuth toma firebaseApp como primer parámetro. La función onAuthStateChanged no está encadenada desde la instancia auth como lo estaría en la API con espacio de nombres; en cambio, es una función gratuita que toma auth como primer parámetro.

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

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

Manejo de actualización del método de autenticación getRedirectResult

La API modular introduce un cambio importante en getRedirectResult . Cuando no se llama a ninguna operación de redireccionamiento, la API modular devuelve null a diferencia de la API con espacio de nombres, que devuelve una UserCredential con un usuario null .

Antes: compatible

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

Después: modular

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;

Ejemplo 2: refactorizar una función de Cloud Firestore

Antes: compatible

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

Después: modular

La función getFirestore toma firebaseApp como primer parámetro, que fue devuelto por initializeApp en un ejemplo anterior. Observe cómo el código para formar una consulta es muy diferente en la API modular; no hay encadenamiento y métodos como query o where ahora se exponen como funciones gratuitas.

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

Actualizar referencias a Firestore DocumentSnapshot.exists

La API modular introduce un cambio importante en el que la propiedad firestore.DocumentSnapshot.exists se ha cambiado a un método . La funcionalidad es esencialmente la misma (probar si existe un documento), pero debes refactorizar tu código para usar el método más nuevo como se muestra:

Antes: compatible

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

Después: modular

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

Ejemplo 3: combinación de estilos de código modular y con espacio de nombres

El uso de las bibliotecas de compatibilidad durante la actualización le permite continuar usando código con espacio de nombres junto con el código refactorizado para la API modular. Esto significa que puedes conservar el código con espacio de nombres existente para Cloud Firestore mientras refactorizas el código de autenticación u otro SDK de Firebase al estilo modular y aun así compilas exitosamente tu aplicación con ambos estilos de código. Lo mismo ocurre con el código API modular y con espacio de nombres dentro de un producto como Cloud Firestore; Los estilos de código nuevos y antiguos pueden coexistir, siempre que importe los paquetes de compatibilidad:

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

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

Tenga en cuenta que, aunque su aplicación se compilará, no obtendrá los beneficios del tamaño de la aplicación del código modular hasta que elimine por completo las declaraciones de compatibilidad y el código de su aplicación.

Actualizar código de inicialización

Actualice el código de inicialización de su aplicación para usar sintaxis modular. Es importante actualizar este código después de haber completado la refactorización de todo el código de su aplicación; esto se debe a que firebase.initializeApp() inicializa el estado global para las API compat y modular, mientras que la función modular initializeApp() inicializa solo el estado para modular.

Antes: compatible

import firebase from "firebase/compat/app"

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

Después: modular

import { initializeApp } from "firebase/app"

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

Eliminar código de compatibilidad

Para obtener los beneficios de tamaño de la API modular, eventualmente debes convertir todas las invocaciones al estilo modular que se muestra arriba y eliminar todas las declaraciones import "firebase/compat/* de tu código. Cuando hayas terminado, no debería haber más referencias. al espacio de nombres global firebase.* o cualquier otro código en el estilo API de espacio de nombres.

Usando la biblioteca de compatibilidad desde la ventana

La API modular está optimizada para funcionar con módulos en lugar del objeto window del navegador. Las versiones anteriores de la biblioteca permitían la carga y administración de Firebase mediante el espacio de nombres window.firebase . No se recomienda esto en el futuro, ya que no permite la eliminación del código no utilizado. Sin embargo, la versión compatible del SDK de JavaScript funciona con la window para los desarrolladores que prefieren no comenzar inmediatamente la ruta de actualización modular.

<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 biblioteca de compatibilidad utiliza código modular interno y le proporciona la misma API que la API con espacio de nombres; esto significa que puede consultar la referencia de la API con espacios de nombres y los fragmentos de código con espacios de nombres para obtener más detalles. Este método no se recomienda para uso a largo plazo, sino como comienzo para actualizar a la biblioteca totalmente modular.

Beneficios y limitaciones del SDK modular

El SDK totalmente modular tiene estas ventajas sobre versiones anteriores:

  • El SDK modular permite reducir drásticamente el tamaño de la aplicación. Adopta el formato moderno del módulo JavaScript, lo que permite prácticas de "sacudida de árboles" en las que importa solo los artefactos que necesita su aplicación. Dependiendo de su aplicación, la agitación de árboles con el SDK modular puede generar un 80 % menos de kilobytes que una aplicación comparable creada con la API de espacio de nombres.
  • El SDK modular seguirá beneficiándose del desarrollo continuo de funciones, mientras que la API con espacio de nombres no.