Organiser plusieurs fonctions


À mesure que vous intégrez Cloud Functions dans votre projet, votre code peut s'étendre pour contenir de nombreuses fonctions indépendantes. Vous pouvez avoir trop de fonctions pour tenir raisonnablement dans un seul fichier, ou différentes équipes peuvent déployer différents groupes de fonctions, créant ainsi un risque qu'une équipe écrase ou supprime accidentellement les fonctions d'une autre équipe. Cloud Functions propose différentes manières d'organiser votre code pour faciliter la navigation et la maintenance de vos fonctions.

Organiser les fonctions dans des bases de code

Vous pouvez utiliser la propriété codebase de l'objet de configuration des fonctions dans firebase.json pour gérer une large collection de fonctions dans plusieurs référentiels ou sous-packages au sein d'une seule configuration monorepo de référentiel :

# 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 propriété codebase est prise en charge dans Firebase CLI v10.7.1 et versions ultérieures.

Gestion de plusieurs référentiels

La propriété codebase peut aider à simplifier la gestion de plusieurs référentiels. Examinons un cas où vous disposez de deux référentiels différents qui déploient des fonctions sur le même projet Firebase :

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

Sans les annotations de la base de code, la CLI Firebase vous aurait invité à supprimer les fonctions définies dans l'autre référentiel au moment du déploiement :

$ (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)

Vous pouvez éviter ce problème en ajoutant une annotation de base de code unique dans la section de configuration des fonctions de firebase.json dans chaque référentiel de projet :

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

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

Avec l'annotation de base de code, la CLI Firebase ne vous invite plus à supprimer les fonctions définies en dehors de votre référentiel immédiat :

$ (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!

Gestion de plusieurs packages sources (monorepo)

La propriété codebase peut contribuer à simplifier la gestion de plusieurs packages sources dans un seul référentiel. Examinons un cas où vous disposez d'un répertoire de projet Firebase avec des définitions de fonctions réparties sur plusieurs sous-packages :

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

Cette configuration correspond aux cas d'utilisation suivants :

  • Vous disposez d'une configuration monorepo et demandez à différentes équipes de gérer leurs propres définitions de fonctions dans un package isolé.
  • Vous disposez d'une fonction avec une forte dépendance externe et une initialisation de longue durée, et souhaitez isoler cette fonction des autres fonctions sensibles à la latence.

Pour prendre en charge la configuration de Monrepo comme celle-ci, définissez plusieurs configurations de fonctions dans firebase.json :

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

Avec cette configuration, la CLI Firebase déploie les fonctions de tous les packages dans une seule commande de déploiement :

$ 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)...
...

Vous pouvez également déployer une base de code spécifique :

$ 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)...
...

Écrire des fonctions dans plusieurs fichiers

Lorsque vous débutez avec Cloud Functions, vous pouvez regrouper vos premières fonctions dans un seul fichier :

index.js

const functions = require('firebase-functions');
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!")

Cela peut devenir difficile à gérer avec plus de quelques fonctions. Au lieu de cela, vous pouvez placer toute votre logique pour chaque fonction dans son propre fichier et utiliser votre fichier source comme liste d'exportations :

Noeud.js

foo.js

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

bar.js

const functions = require('firebase-functions');
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 *

Cette configuration suppose une structure de répertoires de projet comme la suivante :

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

fn_impl : peut avoir n'importe quel nom

__init__.py : obligatoire, mais peut être vide

Fonctions de groupe

Dans de nombreux projets, les fonctions peuvent être séparées en groupes logiques qui doivent être déployés et maintenus ensemble. Par exemple, vous pouvez utiliser un groupe de fonctions pour générer des rapports sur les métriques :

metrics.js


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

Vous pouvez regrouper ces fonctions lors de leur exportation dans votre fichier index.js :

index.js


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

Une fois déployées, les fonctions seront préfixées par le nom de leur groupe, donc dans cet exemple, les fonctions seraient nommées metrics-usageStats et metrics-nightlyReport .

Lors du déploiement de fonctions, vous pouvez limiter l'action à un seul groupe :


firebase deploy --only functions:metrics

Prochaines étapes

Pour en savoir plus sur les fonctions Cloud, consultez :