Man mano che integri Cloud Functions nel tuo progetto, il tuo codice potrebbe espandersi per contenere molte funzioni indipendenti. Potresti avere troppe funzioni per poter essere ragionevolmente inserite in un singolo file, oppure diversi team potrebbero distribuire diversi gruppi di funzioni, creando il rischio che un team sovrascriva o elimini accidentalmente le funzioni di un altro team. Cloud Functions offre diversi modi per organizzare il codice per semplificare la navigazione e la gestione delle funzioni.
Organizzare le funzioni in basi di codice
Puoi utilizzare la proprietà codebase
dell'oggetto di configurazione delle funzioni in firebase.json
per gestire un'ampia raccolta di funzioni su più repository o sottopacchetti all'interno di un'unica configurazione monorepo del repository:
# 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 proprietà codebase
è supportata nella CLI Firebase v10.7.1 e versioni successive.
Gestione di più repository
La proprietà codebase
può aiutare a semplificare la gestione di più repository. Esaminiamo un caso in cui hai due repository diversi che distribuiscono funzioni allo stesso progetto Firebase:
$ tree .
├── repoA
│ ├── firebase.json
│ └── functions
│ ├── index.js
│ └── package.json
└── repoB
├── firebase.json
└── functions
├── index.js
└── package.json
Senza le annotazioni della codebase, la CLI di Firebase ti avrebbe richiesto di eliminare le funzioni definite nell'altro repository al momento della distribuzione:
$ (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)
Puoi evitare questo problema aggiungendo un'annotazione codebase univoca nella sezione di configurazione delle funzioni di firebase.json
in ciascun repository del progetto:
# repoA/firebase.json
"functions": {
"codebase": "repo-a"
}
# repoB/firebase.json
"functions": {
"codebase": "repo-b"
}
Con l'annotazione codebase, la CLI di Firebase non ti chiede più di eliminare le funzioni definite all'esterno del tuo repository immediato:
$ (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!
Gestione di più pacchetti sorgente (monorepo)
La proprietà codebase
può aiutare a semplificare la gestione di più pacchetti di origine in un unico repository. Esaminiamo un caso in cui si dispone di una directory di progetto Firebase con definizioni di funzioni distribuite su diversi sottopacchetti:
$ tree .
├── firebase.json
├── teamA
│ ├── index.js
│ └── package.json
└── teamB
├── index.js
└── package.json
Questa configurazione si adatta ai seguenti casi d'uso:
- Hai una configurazione monorepo e diversi team gestiscono le proprie definizioni di funzioni in un pacchetto isolato.
- Hai una funzione con una forte dipendenza esterna e un'inizializzazione di lunga durata e desideri isolare tale funzione da altre funzioni sensibili alla latenza.
Per supportare la configurazione di monrepo come questa, definisci più configurazioni di funzioni in firebase.json
:
"functions": [
{
"source": "teamA",
"codebase": "team-a"
},
{
"source": "teamB",
"codebase": "team-b"
},
]
Con questa configurazione, la CLI Firebase distribuisce le funzioni di tutti i pacchetti in un unico comando di distribuzione:
$ 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)...
...
Puoi anche distribuire una codebase specifica:
$ 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)...
...
Scrivere funzioni in più file
Quando inizi con Cloud Functions potresti inserire le prime funzioni in un unico file:
indice.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!")
Questo può diventare difficile da gestire con più di poche funzioni. Puoi invece inserire tutta la logica per ciascuna funzione nel proprio file e utilizzare il file sorgente come elenco di esportazioni:
Node.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) => { // ... });
indice.js
const foo = require('./foo'); const bar = require('./bar'); exports.foo = foo.foo; exports.bar = bar.bar;
Pitone
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 *
Questa configurazione presuppone una struttura di directory di progetto come la seguente:
my-project
├── firebase.json
└── functions
├── fn_impl
│ ├── __init__.py
│ ├── foo.py
│ └── bar.py
├── main.py
└── requirements.txt
fn_impl
: può avere qualsiasi nome
__init__.py
: obbligatorio, ma può essere vuoto
Funzioni del gruppo
In molti progetti, le funzioni possono essere separate in gruppi logici che dovrebbero essere distribuiti e mantenuti insieme. Ad esempio, potresti avere un gruppo di funzioni utilizzate per la creazione di report sulle metriche:
metrics.js
const functions = require('firebase-functions'); exports.usageStats = functions.https.onRequest((request, response) => { // ... }); exports.nightlyReport = functions.https.onRequest((request, response) => { // ... });
Puoi inserire queste funzioni in un gruppo quando le esporti nel tuo file index.js
:
indice.js
// Export both functions from metrics.js in the "metrics" group: // - metrics-usageStats // - metrics-nightlyReport exports.metrics = require('./metrics');
Una volta distribuite, le funzioni avranno il prefisso con il nome del relativo gruppo, quindi in questo esempio le funzioni verrebbero denominate metrics-usageStats
e metrics-nightlyReport
.
Quando si distribuiscono le funzioni è possibile limitare l'azione a un singolo gruppo:
firebase deploy --only functions:metrics
Prossimi passi
Per ulteriori informazioni su Cloud Functions, consulta: