W miarę integrowania Cloud Functions z projektem kod może się rozrastać i zawierać wiele niezależnych funkcji. Może się zdarzyć, że masz zbyt wiele funkcji, aby zmieścić je w jednym pliku, lub różne zespoły mogą wdrażać różne grupy funkcji, co stwarza ryzyko nadpisania lub przypadkowego usunięcia funkcji innego zespołu. Cloud Functions oferuje różne sposoby organizowania kodu, aby ułatwić poruszanie się po funkcjach i ich obsługę.
Porządkowanie funkcji w bazach kodu
W obiekcie konfiguracji funkcji możesz użyć właściwości codebase
, aby zarządzać dużą kolekcją funkcji w wielu repozytoriach lub podpakietach w ramach konfiguracji monorepo w jednym repozytorium:firebase.json
# 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.
}
Właściwość codebase
jest obsługiwana w wierszu poleceń Firebase w wersji 10.7.1 i nowszych.
Zarządzanie wieloma repozytoriami
Właściwość codebase
może ułatwić zarządzanie wieloma repozytoriami. Przyjrzyjmy się sytuacji, w której masz 2 różne repozytoria, które wdrażają funkcje w tym samym projekcie Firebase:
$ tree .
├── repoA
│ ├── firebase.json
│ └── functions
│ ├── index.js
│ └── package.json
└── repoB
├── firebase.json
└── functions
├── index.js
└── package.json
Bez adnotacji w bazie kodu wiersz poleceń Firebase poprosiłby Cię o usunięcie funkcji zdefiniowanych w innym repozytorium w momencie wdrażania:
$ (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)
Aby uniknąć tego problemu, dodaj unikalną adnotację do bazy kodu w sekcji konfiguracji funkcji w pliku firebase.json
w każdym repozytorium projektu:
# repoA/firebase.json
"functions": {
"codebase": "repo-a"
}
# repoB/firebase.json
"functions": {
"codebase": "repo-b"
}
Dzięki adnotacjom w kodzie wiersz poleceń Firebase nie będzie już wyświetlać prośby o usunięcie funkcji zdefiniowanych poza bezpośrednim repozytorium:
$ (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!
Zarządzanie wieloma pakietami źródłowymi (monorepo)
Właściwość codebase
może ułatwić zarządzanie wieloma pakietami źródłowymi w jednym repozytorium. Przyjrzyjmy się przypadkowi, w którym masz katalog projektu Firebase z definicjami funkcji rozproszonymi w kilku podpakietach:
$ tree .
├── firebase.json
├── teamA
│ ├── index.js
│ └── package.json
└── teamB
├── index.js
└── package.json
Ta konfiguracja pasuje do tych przypadków użycia:
- Masz konfigurację monorepo i różne zespoły zarządzają własnymi definicjami funkcji w izolowanym pakiecie.
- Masz funkcję z dużą liczbą zależności zewnętrznych i długotrwałą inicjalizacją, którą chcesz odizolować od innych funkcji wrażliwych na opóźnienia.
Aby obsługiwać konfigurację monorepo, zdefiniuj wiele konfiguracji funkcji w firebase.json
:
"functions": [
{
"source": "teamA",
"codebase": "team-a"
},
{
"source": "teamB",
"codebase": "team-b"
},
]
W tej konfiguracji wiersz poleceń Firebase wdraża funkcje ze wszystkich pakietów za pomocą jednego polecenia wdrażania:
$ 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)...
...
Możesz też wdrożyć konkretną bazę kodu:
$ 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)...
...
Pisanie funkcji w wielu plikach
Na początku pracy z Cloud Functions możesz umieścić pierwsze funkcje w jednym pliku:
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!")
Gdy funkcji jest więcej niż kilka, zarządzanie nimi może być trudne. Zamiast tego możesz umieścić całą logikę każdej funkcji w osobnym pliku i użyć pliku źródłowego jako listy eksportów:
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 *
Ta konfiguracja zakłada strukturę katalogu projektu podobną do tej:
my-project
├── firebase.json
└── functions
├── fn_impl
│ ├── __init__.py
│ ├── foo.py
│ └── bar.py
├── main.py
└── requirements.txt
fn_impl
: może mieć dowolną nazwę
__init__.py
: wymagany, ale może być pusty
Funkcje grupowe
W wielu projektach funkcje można podzielić na logiczne grupy, które powinny być wdrażane i utrzymywane razem. Możesz na przykład mieć grupę funkcji używanych do raportowania danych:
metrics.js
const functions = require('firebase-functions/v1'); exports.usageStats = functions.https.onRequest((request, response) => { // ... }); exports.nightlyReport = functions.https.onRequest((request, response) => { // ... });
Podczas eksportowania tych funkcji w pliku index.js
możesz je umieścić w grupie:
index.js
// Export both functions from metrics.js in the "metrics" group: // - metrics-usageStats // - metrics-nightlyReport exports.metrics = require('./metrics');
Po wdrożeniu funkcje będą miały prefiks w postaci nazwy grupy, więc w tym przykładzie funkcje będą się nazywać metrics-usageStats
i metrics-nightlyReport
.
Podczas wdrażania funkcji możesz ograniczyć działanie do jednej grupy:
firebase deploy --only functions:metrics
Dalsze kroki
Więcej informacji o Cloud Functions znajdziesz w tych artykułach: