Организуйте несколько функций


По мере интеграции облачных функций в ваш проект ваш код может расширяться и включать множество независимых функций. У вас может быть слишком много функций, чтобы разумно уместить их в одном файле, или разные команды могут развертывать разные группы функций, создавая риск перезаписи или случайного удаления функций другой команды одной командой. Cloud Functions предлагает различные способы организации вашего кода, чтобы упростить навигацию и поддержку ваших функций.

Организация функций в базах кода

Вы можете использовать свойство codebase объекта конфигурации функций в 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.
}

Свойство codebase поддерживается в Firebase CLI v10.7.1 и более поздних версиях.

Управление несколькими репозиториями

Свойство codebase может помочь упростить управление несколькими репозиториями. Давайте рассмотрим случай, когда у вас есть два разных репозитория, которые развертывают функции в одном проекте Firebase:

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

Без аннотаций кодовой базы интерфейс командной строки Firebase предложил бы вам удалить функции, определенные в другом репозитории во время развертывания:

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

Вы можете избежать этой проблемы, добавив уникальную аннотацию кодовой базы в раздел конфигурации функций firebase.json в каждом репозитории проекта:

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

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

Благодаря аннотации кодовой базы интерфейс командной строки Firebase больше не предлагает вам удалить функции, определенные за пределами вашего непосредственного репозитория:

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

Управление несколькими исходными пакетами (монорепо)

Свойство codebase может помочь упростить управление несколькими исходными пакетами в одном репозитории. Давайте рассмотрим случай, когда у вас есть каталог проекта Firebase с определениями функций, распределенными по нескольким подпакетам:

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

Эта установка подходит для следующих случаев использования:

  • У вас есть настройка монорепозитория , и разные команды управляют своими собственными определениями функций в изолированном пакете.
  • У вас есть функция с сильной внешней зависимостью и длительной инициализацией, и вы хотите изолировать эту функцию от других функций, чувствительных к задержке.

Чтобы поддерживать такую ​​настройку monrepo, определите несколько конфигураций функций в firebase.json :

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

В этой конфигурации интерфейс командной строки Firebase развертывает функции из всех пакетов с помощью одной команды развертывания:

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

Вы также можете развернуть определенную кодовую базу:

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

Запись функций в нескольких файлах

Приступая к работе с облачными функциями, вы можете поместить несколько первых функций в один файл:

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

С этим может оказаться сложно справиться, если использовать несколько функций. Вместо этого вы можете поместить всю логику для каждой функции в отдельный файл и использовать исходный файл в качестве списка экспорта:

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) => {
  // ...
});

index.js

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

Питон

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

бар.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 *

Эта установка предполагает структуру каталогов проекта, подобную следующей:

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

fn_impl : может иметь любое имя

__init__.py : обязателен, но может быть пустым.

Групповые функции

Во многих проектах функции можно разделить на логические группы, которые следует развертывать и обслуживать вместе. Например, у вас может быть группа функций, используемых для отчетности по метрикам:

metrics.js


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

Вы можете объединить эти функции в группу при их экспорте в файл index.js :

index.js


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

При развертывании перед функциями будет стоять имя их группы, поэтому в этом примере функции будут называться metrics-usageStats и metrics-nightlyReport .

При развертывании функций вы можете ограничить действие одной группой:


firebase deploy --only functions:metrics

Следующие шаги

Дополнительные сведения об облачных функциях см. в статьях: