Организация нескольких функций (1-е поколение)

As you integrate Cloud Functions into your project, your code could expand to contain many independent functions. You may have too many functions to reasonably fit in a single file, or different teams may deploy different groups of functions, creating a risk of one team overwriting or accidentally deleting another team's functions. Cloud Functions offers different ways to organize your code to make it easier to navigate and maintain your functions.

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

Для управления большим количеством функций в нескольких репозиториях или подпакетах в рамках одной монорепозитории можно использовать свойство codebase объекта конфигурации functions в 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 версии 10.7.1 и выше.

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

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

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

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

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

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

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

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

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

$ (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 CLI развертывает функции из всех пакетов одной командой развертывания:

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

Напишите функции в нескольких файлах.

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

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

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

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 *

Данная конфигурация предполагает следующую структуру каталогов проекта:

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/v1');
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

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

Чтобы узнать больше о Cloud Functions , см.: