Zorganizuj wiele funkcji


Gdy zintegrujesz Cloud Functions ze swoim projektem, Twój kod może rozszerzyć się i zawierać wiele niezależnych funkcji. Możesz mieć zbyt wiele funkcji, aby zmieścić się w jednym pliku, lub różne zespoły mogą wdrażać różne grupy funkcji, stwarzając ryzyko nadpisania lub przypadkowego usunięcia przez jeden zespół funkcji innego zespołu. Cloud Functions oferuje różne sposoby organizowania kodu, aby ułatwić nawigację i konserwację funkcji.

Organizuj funkcje w bazach kodu

Możesz użyć właściwości codebase obiektu konfiguracji funkcji w firebase.json , aby zarządzać dużą kolekcją funkcji w wielu repozytoriach lub podpakietach w ramach jednej konfiguracji monorepo w jednym repozytorium:

# 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 Firebase CLI w wersji 10.7.1 i nowszych.

Zarządzanie wieloma repozytoriami

Właściwość codebase może uprościć zarządzanie wieloma repozytoriami. Przeanalizujmy przypadek, w którym masz dwa 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 interfejs CLI Firebase poprosiłby o usunięcie funkcji zdefiniowanych w innym repozytorium w momencie wdrożenia:

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

Możesz uniknąć tego problemu, dodając unikalną adnotację bazy kodu w sekcji konfiguracji funkcji firebase.json w każdym repozytorium projektu:

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

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

Dzięki adnotacji w bazie kodu interfejs CLI Firebase nie wyświetla już monitu 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 pomóc uprościć zarządzanie wieloma pakietami źródłowymi w jednym repozytorium. Przeanalizujmy przypadek, w którym masz katalog projektu Firebase z definicjami funkcji rozmieszczonymi w kilku podpakietach:

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

Ta konfiguracja pasuje do następujących przypadków użycia:

  • Masz konfigurację monorepo i różne zespoły zarządzają własnymi definicjami funkcji w izolowanym pakiecie.
  • Masz funkcję o dużej zależności zewnętrznej i długotrwałej inicjalizacji i chcesz odizolować tę funkcję od innych funkcji wrażliwych na opóźnienia.

Aby obsługiwać taką konfigurację monrepo, zdefiniuj konfiguracje wielu funkcji w firebase.json :

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

W tej konfiguracji interfejs CLI 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 także wdrożyć określoną 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)...
...

Zapisz funkcje w wielu plikach

Rozpoczynając pracę z Cloud Functions, możesz umieścić kilka pierwszych funkcji w jednym pliku:

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

Zarządzanie tym może być trudne w przypadku więcej niż kilku funkcji. Zamiast tego możesz umieścić całą logikę dla 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');
exports.foo = functions.https.onRequest((request, response) => {
  // ...
});

bar.js

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

indeks.js

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

Pyton

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 *

W tej konfiguracji przyjęto następującą strukturę katalogów projektu:

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 należy wspólnie wdrażać i utrzymywać. Na przykład możesz mieć grupę funkcji używanych do raportowania metryk:

metrics.js


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

Możesz umieścić te funkcje w grupie podczas eksportowania ich do pliku index.js :

indeks.js


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

Po wdrożeniu funkcje zostaną poprzedzone nazwą ich grupy, więc w tym przykładzie funkcje będą miały nazwy metrics-usageStats i metrics-nightlyReport .

Podczas wdrażania funkcji możesz ograniczyć akcję do pojedynczej grupy:


firebase deploy --only functions:metrics

Następne kroki

Aby dowiedzieć się więcej o funkcjach chmury, zobacz: