Migración de Extensión a Base de Código de Functions y Paquete npm
Resumen
Migra una extensión de Firebase a uno de los siguientes formatos:
- Una base de código local de Cloud Functions (
functions/src/para integración en la aplicación). - Un paquete npm publicable (paquete reutilizable de código abierto que exporta funciones V2).
Aprovecha las características nativas de Cloud Functions (IAM declarativo, Configuración Parametrizada, Hooks de Ciclo de Vida del SDK) y moderniza los disparadores de 1.ª Generación a 2.ª Generación utilizando el Destructuring Compatibility Shim.
Flujos de Migración Objetivo
-
Objetivo A: Base de Código Local de Functions (Integración en Aplicación de Usuario Final)
- Salida: Código en
functions/src/. Configuración en.env. - Despliegue:
firebase deploy --only functions.
- Salida: Código en
-
Objetivo B: Paquete npm Publicable / Paquete Compartible
- Salida: Paquete npm reutilizable que exporta funciones V2.
- Configuración:
package.jsonespecificando el mapaexports,engines: { "node": ">=22" }, ypeerDependencies: { "firebase-functions": ">=6.0.0" }. - Uso: Los consumidores instalan el paquete y reexportan funciones en
index.ts(export * from "<nombre-del-paquete>").
Reglas y Restricciones Principales
1. IAM y APIs Declarativos (Sin Sobrecarga Local)
Usa declaraciones nativas del SDK en lugar de scripts gcloud manuales o instrucciones de consola:
- Usa
requiresRole("roles/...")para permisos IAM de GCP requeridos. - Usa
requiresAPI("service.googleapis.com", "Descripción")para APIs de Google.
2. Restricción de Acceso a Parámetros Globales
- Nunca llames a
.value()en el ámbito de carga del módulo de nivel superior. - Inicializa las instancias globales del SDK dentro de
onInit()o getters perezosos:import { defineString } from "firebase-functions/params"; import { onInit } from "firebase-functions/v2"; const dataset = defineString("DATASET_ID"); let client: BigQuery; onInit(() => { client = new BigQuery({ datasetId: dataset.value() }); });
3. Concurrencia V2 y Paridad de Costos
V2 permite concurrencia (hasta 80 solicitudes). Para preservar el precio de concurrencia única de V1, establece cpu: "gcf_gen1".
Ejecución de Migración Paso a Paso
Paso 1: Inventariar Recursos de la Extensión
extension.yaml:params→defineString,defineInt,defineBoolean,defineSecret.apis→requiresAPI(...).roles→requiresRole(...).lifecycleEvents→afterFirstDeployyafterRedeploy.resources→ Actualiza los disparadores de 1.ª Generación a 2.ª Generación (onDocumentWritten,onTaskDispatched,onRequest).
- Archivos y Scripts: Conserva las devDependencies, el framework de pruebas (
jest) y los scripts de prueba.
Paso 2: Configurar package.json
- Establece
name: "<nombre-del-paquete>",engines: { "node": ">=22" }. - Establece
peerDependencies:"peerDependencies": { "firebase-admin": "^11.0.0 || ^12.0.0", "firebase-functions": ">=6.0.0" } - Configura el mapa
exportsapuntando a ESM/CommonJS y declaraciones TypeScript (lib/index.js,lib/index.d.ts).
Paso 3: Actualizar Disparadores de V1 a V2
- Firestore: Usa
onDocumentWrittendesdefirebase-functions/v2/firestore. - Tasks: Usa
onTaskDispatcheddesdefirebase-functions/v2/tasks. EliminaEXT_INSTANCE_IDal encolar tareas. - HTTP: Usa
onRequestdesdefirebase-functions/v2/https. - Aplica el Destructuring Compatibility Shim (
{ change, context },{ snapshot, context }) donde los manejadores heredados de 1.ª Generación esperan(change, context).
Paso 4: Convertir Eventos de Ciclo de Vida
Asigna los eventos de ciclo de vida de la extensión a los hooks de ciclo de vida del SDK en src/index.ts:
onInstall→afterFirstDeploy({ task: { function: "initTask" } })onUpdate/onConfigure→afterRedeploy({ task: { function: "setupTask" } })
Paso 5: README del Paquete e Instrucciones de Exportación
Genera README.md que contenga:
- Instrucciones de instalación (
npm install). - Fragmento de reexportación (
export * from "<nombre-del-paquete>"). - Tabla de referencia de configuración parametrizada
.env. - Tabla de comparación de cambios (Extensión vs Paquete).
Recuerda: NUNCA ejecutes npm publish.