Organiza varias funciones


A medida que integras Cloud Functions en tu proyecto, tu código podría expandirse para contener muchas funciones independientes. Es posible que tengas demasiadas funciones y que no sea razonable mantenerlas en un solo archivo, o bien que equipos distintos implementen diferentes grupos de funciones, lo que implica el riesgo de que un equipo reemplace o borre accidentalmente las funciones de otro. Cloud Functions ofrece diferentes formas de organizar el código para facilitar navegación y el mantenimiento de las funciones.

Organiza funciones en bases de código

Puedes usar la propiedad codebase del objeto de configuración de funciones en firebase.json para administrar un gran conjunto de funciones alojadas en múltiples repositorios o subpaquetes en una configuración de un solo repositorio (monorepo):

# firebase.json
"functions": {
  "codebase": "my-codebase"
  # NOTE: Codebase must be less than 63 characters and can contain only
  # lowercase letters, numeric characters, underscores, and dashes.
}

La propiedad codebase es compatible con Firebase CLI 10.7.1 y versiones posteriores.

Administra múltiples repositorios

La propiedad codebase puede ayudarte a simplificar la administración de múltiples repositorios. Examinemos un caso en el que tienes dos repositorios diferentes que implementan funciones en el mismo proyecto de Firebase:

$  tree .
├── repoA
│   ├── firebase.json
│   └── functions
│       ├── index.js
│       └── package.json
└── repoB
    ├── firebase.json
    └── functions
        ├── index.js
        └── package.json

Sin las anotaciones de base de código, Firebase CLI te habría solicitado borrar las funciones definidas en el otro repositorio en el momento de la implementación:

$ (cd repoA && firebase deploy --only functions)
...
i  functions: preparing functions directory for uploading...
  functions: functions folder uploaded successfully
The following functions are found in your project but do not exist in your local source code:
        fn1FromRepoB
        fn2FromRepoB
        ...
? Would you like to proceed with deletion? Selecting no will continue the rest of the deployments. (y/N)

Para evitar este problema, puedes agregar una anotación única de base de código en la sección de configuración de funciones de firebase.json en cada repositorio del proyecto:

# repoA/firebase.json
"functions": {
  "codebase": "repo-a"
}

# repoB/firebase.json
"functions": {
  "codebase": "repo-b"
}

Con la anotación de base de código, Firebase CLI ya no solicita que borres funciones definidas fuera de tu repositorio inmediato:

$ (cd repoA && firebase deploy --only functions)
...
i  functions: preparing functions directory for uploading...
  functions: functions folder uploaded successfully
#  Gleefully ignores functions from repoB
i  functions: creating Node.js 16 function fnFromRepoA (us-central1)...
  Deploy Complete!

Administra múltiples paquetes de código fuente (monorepo)

La propiedad codebase puede ayudarte a simplificar la administración de múltiples paquetes de código fuente en un solo repositorio. Examinemos un caso en el que tengas un directorio de proyecto de Firebase con definiciones de funciones distribuidas en numerosos subpaquetes:

$  tree .
├── firebase.json
├── teamA
│   ├── index.js
│   └── package.json
└── teamB
    ├── index.js
    └── package.json

Esta configuración se ajusta a los siguientes casos de uso:

  • Tienes una configuración de monorepo y equipos diferentes administran sus propias definiciones de funciones en un paquete aislado.
  • Tienes una función con muchas dependencias externas y una inicialización de larga duración, y deseas aislarla de otras funciones sensibles a la latencia.

Para admitir la configuración monorepo de esta manera, define múltiples parámetros de configuración de funciones en firebase.json:

"functions": [
  {
    "source": "teamA",
    "codebase": "team-a"
  },
  {
    "source": "teamB",
    "codebase": "team-b"
  },
]

Con esta configuración, Firebase CLI implementa funciones de todos los paquetes en un solo comando de implementación:

$ firebase deploy --only functions
i  deploying functions
i  functions: preparing codebase team-a for deployment
i  functions: preparing codebase team-b for deployment
i  functions: creating Node.js 16 function team-a:helloATeam(us-central1)...
i  functions: creating Node.js 16 function team-b:helloBTeam(us-central1)...
...

También puedes implementar una base de código específica:

$ firebase deploy --only functions:team-b
i  deploying functions
i  functions: preparing codebase team-b for deployment
i  functions: updating Node.js 16 function team-b:helloBTeam(us-central1)...
...

Escribe funciones en varios archivos

Cuando comiences a usar Cloud Functions, puedes colocar tus primeras funciones en un solo archivo:

index.js

const functions = require('firebase-functions/v1');
exports.foo = functions.https.onRequest((request, response) => {
  // ...
});
exports.bar = functions.https.onRequest((request, response) => {
  // ...
});

main.py

from firebase_functions import https_fn

@https_fn.on_request()
def foo(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello foo!")

@https_fn.on_request()
def bar(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello bar!")

Esto puede ser difícil de administrar con más de unas pocas funciones. En su lugar, puedes colocar toda tu lógica para cada función en su propio archivo y usar tu archivo como una lista simple de exportaciones:

Node.js

foo.js

const functions = require('firebase-functions/v1');
exports.foo = functions.https.onRequest((request, response) => {
  // ...
});

bar.js

const functions = require('firebase-functions/v1');
exports.bar = functions.https.onRequest((request, response) => {
  // ...
});

index.js

const foo = require('./foo');
const bar = require('./bar');
exports.foo = foo.foo;
exports.bar = bar.bar;

Python

foo.py

from firebase_functions import https_fn

@https_fn.on_request()
def foo(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello foo!")

bar.py

from firebase_functions import https_fn

@https_fn.on_request()
def bar(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello foo!")

main.py

from fn_impl.foo import *
from fn_impl.bar import *

En esta configuración, se supone una estructura de directorios del proyecto como la siguiente:

my-project
├── firebase.json
└── functions
    ├── fn_impl
    │   ├── __init__.py
    │   ├── foo.py
    │   └── bar.py
    ├── main.py
    └── requirements.txt

fn_impl: Puede tener cualquier nombre.

__init__.py: Obligatorio, pero puede estar vacío

Agrupa funciones

En muchos proyectos, las funciones se pueden separar en grupos lógicos que se deben implementar y mantener juntos. Por ejemplo, puedes tener un grupo de funciones que se usan para informar métricas:

metrics.js


const functions = require('firebase-functions/v1');
exports.usageStats = functions.https.onRequest((request, response) => {
  // ...
});
exports.nightlyReport = functions.https.onRequest((request, response) => {
  // ...
});

Puedes colocar estas funciones en un grupo cuando las exportes en tu archivo index.js:

index.js


// Export both functions from metrics.js in the "metrics" group:
//  - metrics-usageStats
//  - metrics-nightlyReport
exports.metrics = require('./metrics');

Cuando se implementan, las funciones tendrán el prefijo del nombre de su grupo, por lo que en este ejemplo las funciones se llamarían metrics-usageStats y metrics-nightlyReport.

Cuando implementas funciones, puedes limitar la acción a un solo grupo:


firebase deploy --only functions:metrics

Próximos pasos

Para obtener más información sobre Cloud Functions, consulta los siguientes vínculos: