Organizza più funzioni


Man mano che integri Cloud Functions nel tuo progetto, il codice potrebbe espandersi in contengono molte funzioni indipendenti. Potresti avere troppe funzioni possono essere ragionevolmente contenute in un unico file, oppure team diversi possono eseguire il deployment di gruppi diversi di funzioni, con 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 nei codebase

Puoi utilizzare la proprietà codebase dell'oggetto di configurazione delle funzioni in firebase.json per gestire una grande raccolta di funzioni in più repository o sottopacchetti all'interno di un'unica configurazione monorepo di 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 nell'interfaccia a riga di comando di Firebase 10.7.1 e versioni successive.

Gestione di più repository

La proprietà codebase può contribuire a semplificare la gestione di più repository. Esaminiamo un caso in cui hai due repository diversi che eseguono il deployment di funzioni nello stesso progetto Firebase:

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

Senza le annotazioni codebase, l'interfaccia a riga di comando di Firebase ti avrebbe richiesto di le funzioni di eliminazione definite nell'altro repository al momento del deployment:

$ (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 univoca del codebase nella sezione di configurazione delle funzioni di firebase.json in ogni repository di progetto:

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

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

Con l'annotazione codebase, l'interfaccia a riga di comando di Firebase non richiede più l'eliminazione di funzioni definite all'esterno del 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 di origine (monorepo)

La proprietà codebase può contribuire a semplificare la gestione di più origini di pacchetti in un unico repository. Esaminiamo un caso in cui hai una directory del progetto Firebase con definizioni di funzioni distribuite su più sottopacchetti:

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

Questa configurazione è adatta ai seguenti casi d'uso:

  • Hai una configurazione monorepo e diversi team gestiscono le proprie definizioni delle funzioni in un pacchetto isolato.
  • Hai una funzione con una dipendenza esterna elevata e un'inizializzazione a lunga esecuzione e vuoi isolarla da altre funzioni sensibili alla latenza.

Per supportare una configurazione monrepo come questa, definisci più configurazioni di funzioni tra firebase.json:

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

Con questa configurazione, l'interfaccia a riga di comando di Firebase esegue il deployment delle funzioni di tutti i pacchetti in un unico comando di deployment:

$ 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 eseguire il deployment di 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 a usare Cloud Functions, potresti mettere i tuoi primi in un singolo file:

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!")

Questo può diventare difficile da gestire con più di alcune funzioni. Invece, puoi inserire tutta la logica per ogni funzione in un file separato e utilizzare di origine come elenco delle esportazioni:

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 *

Questa configurazione presuppone una struttura di directory di progetto simile alla 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: campo obbligatorio, ma può essere vuoto

Funzioni di gruppo

In molti progetti, le funzioni possono essere separate in gruppi logici, il deployment e la manutenzione. Ad esempio, potresti avere un gruppo funzioni utilizzate per le metriche di reporting:

metrics.js


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

Puoi inserire queste funzioni in un gruppo quando le esporti in index.js file:

index.js


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

Al momento del deployment, alle funzioni sarà aggiunto il prefisso del nome del gruppo, in questo esempio le funzioni vengono denominate metrics-usageStats e metrics-nightlyReport.

Quando esegui il deployment di funzioni, puoi limitare l'azione a un singolo gruppo:


firebase deploy --only functions:metrics

Passaggi successivi

Per scoprire di più su Cloud Functions, consulta: