Как управлять функциями (первое поколение)

Вы можете развертывать, удалять и изменять функции с помощью команд Firebase CLI или задавая параметры среды выполнения в исходном коде функций.

Как развернуть функции

Чтобы развернуть функции, выполните следующую команду CLI Firebase:

firebase deploy --only functions

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

firebase deploy --only functions:addMessage,functions:makeUppercase

При развертывании большого количества функций вы можете превысить стандартную квоту и получить сообщения об ошибках HTTP 429 или 500. Чтобы решить эту проблему, развертывайте функции группами по 10 или меньше.

Полный список доступных команд приведен в справочнике по CLI Firebase.

По умолчанию интерфейс командной строки Firebase ищет исходный код в папке functions/. При необходимости вы можете организовать функции в кодовых базах или нескольких наборах файлов.

Удалить функции

Удалить ранее развернутые функции можно следующими способами:

  • явно в CLI Firebase с помощью functions:delete.
  • в явном виде в консоли Google Cloud.
  • неявно, удалив функцию из источника до развертывания.

При удалении функции из рабочей версии вам будет предложено подтвердить действие.

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

  • Удаляет все функции с указанным названием во всех регионах:

    firebase functions:delete FUNCTION-1_NAME

  • Удаляет указанную функцию, выполняющуюся в регионе, отличном от региона по умолчанию:

    firebase functions:delete FUNCTION-1_NAME --region REGION_NAME

  • Удаляет несколько функций:

    firebase functions:delete FUNCTION-1_NAME FUNCTION-2_NAME

  • Удаляет указанную группу функций:

    firebase functions:delete GROUP_NAME

  • Пропускает запрос подтверждения:

    firebase functions:delete FUNCTION-1_NAME --force

При неявном удалении функций firebase deploy анализирует источник и удаляет из рабочей версии все функции, которые были удалены из файла.

Как изменить название, регион или триггер функции

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

Как переименовать функцию

Чтобы переименовать функцию, создайте новую версию функции с новым названием в исходном коде, а затем выполните две отдельные команды развертывания. Первая команда развертывает функцию с новым названием, а вторая удаляет ранее развернутую версию. Например, если у вас есть функция Node.js с названием webhook, которое вы хотите изменить на webhookNew, измените код следующим образом:

// before
const functions = require('firebase-functions/v1');

exports.webhook = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

// after
const functions = require('firebase-functions/v1');

exports.webhookNew = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

Затем выполните следующие команды, чтобы развернуть новую функцию:

# Deploy new function called webhookNew
firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both webhookNew and webhook are running

# Delete webhook
firebase functions:delete webhook

Как изменить регион или регионы функции

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

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

Например, если у вас есть функция webhook, которая сейчас развернута в регионе us-central1, и вы хотите перенести ее в регион asia-northeast1, вам нужно сначала изменить исходный код, чтобы переименовать функцию и изменить регион.

// before
const functions = require('firebase-functions/v1');

exports.webhook = functions
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

// after
const functions = require('firebase-functions/v1');

exports.webhookAsia = functions
    .region('asia-northeast1')
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

Затем разверните его, выполнив следующую команду:

firebase deploy --only functions:webhookAsia

Теперь выполняются две одинаковые функции: webhook в us-central1 и webhookAsia в asia-northeast1.

Затем удалите webhook:

firebase functions:delete webhook

Теперь есть только одна функция – webhookAsia, которая выполняется в asia-northeast1.

Как изменить тип триггера функции

По мере развития развертывания Cloud Functions for Firebase может возникнуть необходимость изменить тип триггера функции по разным причинам. Например, вы можете захотеть изменить тип события Firebase Realtime Database или Cloud Firestore.

Нельзя изменить тип события функции, просто изменив исходный код и запустив firebase deploy. Чтобы избежать ошибок, измените тип триггера функции, выполнив следующие действия:

  1. Измените исходный код, добавив новую функцию с нужным типом триггера.
  2. Разверните функцию, чтобы временно запустить старую и новую функции.
  3. Явно удалите старую функцию из рабочей среды с помощью интерфейса командной строки Firebase.

Например, если у вас есть функция Node.js с названием objectChanged и устаревшим типом события onChange, и вы хотите изменить тип события на onFinalize, сначала переименуйте функцию, а затем измените ее, чтобы она использовала тип события onFinalize.

// before
const functions = require('firebase-functions/v1');

exports.objectChanged = functions.storage.object().onChange((object) => {
    return console.log('File name is: ', object.name);
});

// after
const functions = require('firebase-functions/v1');

exports.objectFinalized = functions.storage.object().onFinalize((object) => {
    return console.log('File name is: ', object.name);
});

Затем выполните следующие команды, чтобы сначала создать новую функцию, а затем удалить старую:

# Create new function objectFinalized
firebase deploy --only functions:objectFinalized

# Wait until deployment is done; now both objectChanged and objectFinalized are running

# Delete objectChanged
firebase functions:delete objectChanged

Как задать настройки среды выполнения

Cloud Functions for Firebase позволяет выбирать параметры среды выполнения, например версию среды выполнения Node.js, а также время ожидания, выделение памяти и минимальное/максимальное количество экземпляров функции.

Рекомендуем задавать эти параметры (кроме версии Node.js) в объекте конфигурации внутри кода функции. Этот RuntimeOptions объект является источником достоверной информации о параметрах выполнения функции и переопределяет параметры, заданные любым другим способом (например, с помощью консоли Google Cloud или gcloud CLI).

Если в процессе разработки вы вручную задаете параметры времени выполнения с помощью консоли Google Cloud или gcloud CLI и не хотите, чтобы эти значения переопределялись при каждом развертывании, задайте для параметра preserveExternalChanges значение true. Если задано значение true, Firebase объединяет параметры времени выполнения, заданные в коде, с настройками текущей развернутой версии функции в следующем порядке приоритета:

  1. Параметр задан в коде функций: переопределить внешние изменения.
  2. В коде функций задан параметр RESET_VALUE: внешние изменения переопределяются значением по умолчанию.
  3. Параметр не задан в коде функций, но задан в развернутой функции: используйте параметр, указанный в развернутой функции.

Использовать вариант preserveExternalChanges: true в большинстве случаев не рекомендуется, поскольку ваш код перестанет быть единственным источником информации о параметрах среды выполнения для ваших функций. Если вы используете его, проверьте консоль Google Cloud или используйте gcloud CLI, чтобы посмотреть полную конфигурацию функции.

Как задать версию Node.js

Firebase SDK для Cloud Functions позволяет выбрать среду выполнения Node.js. Вы можете настроить выполнение всех функций в проекте исключительно в среде выполнения, соответствующей одной из следующих поддерживаемых версий Node.js:

  • Node.js 22
  • Node.js 20
  • Node.js 18 (устаревшая версия)

Ознакомьтесь с графиком поддержки, чтобы узнать важную информацию о поддержке этих версий Node.js.

Чтобы задать версию Node.js:

Вы можете задать версию в поле engines в файле package.json, который был создан в каталоге functions/ во время инициализации. Например, чтобы использовать только версию 20, измените следующую строку в файле package.json:

  "engines": {"node": "22"}

Если вы используете менеджер пакетов Yarn или у вас есть другие особые требования к полю engines, вы можете задать среду выполнения для SDK Firebase для Cloud Functions в файле firebase.json:

  {
    "functions": {
      "runtime": "nodejs22"
    }
  }

CLI использует значение, заданное в firebase.json, вместо любого значения или диапазона, которые вы задали отдельно в package.json.

Как обновить среду выполнения Node.js

Чтобы обновить среду выполнения Node.js:

  1. Убедитесь, что для вашего проекта выбран тарифный план Blaze.
  2. Убедитесь, что вы используете Firebase CLI версии 11.18.0 или более поздней.
  3. Измените значение engines в файле package.json, который был создан в каталоге functions/ во время инициализации. Например, если вы переходите с версии 16 на версию 18, запись должна выглядеть так: "engines": {"node": "18"}
  4. При необходимости проверьте изменения с помощью Firebase Local Emulator Suite.
  5. Повторно разверните все функции.

Как выбрать систему модулей Node.js

По умолчанию в Node.js используется система модулей CommonJS (CJS), но текущие версии Node.js также поддерживают модули ECMAScript (ESM). Cloud Functions поддерживает оба варианта.

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

const functions = require("firebase-functions/v1");

exports.helloWorld = functions.https.onRequest(async (req, res) => res.send("Hello from Firebase!"));

Чтобы использовать ESM, задайте значение "type": "module" в файле package.json:

  {
   ...
   "type": "module",
   ...
  }

После этого используйте синтаксис ESM import и export:

import functions from "firebase-functions/v1";

export const helloWorld = functions.https.onRequest(async (req, res) => res.send("Hello from Firebase!"));

Обе системы модулей полностью поддерживаются. Выберите тот, который лучше всего подходит для вашего проекта. Подробнее о модулях в Node.js…

Как управлять масштабированием

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

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

Как уменьшить количество холодных запусков

Чтобы задать минимальное количество экземпляров для функции в исходном коде, используйте метод runWith. Этот метод принимает объект JSON, соответствующий интерфейсу RuntimeOptions, который определяет значение для minInstances. Например, эта функция задает минимальное количество экземпляров, которые должны быть активны, равное пяти:

exports.getAutocompleteResponse = functions
    .runWith({
      // Keep 5 instances warm for this latency-critical function
      minInstances: 5,
    })
    .https.onCall((data, context) => {
      // Autocomplete a user's search term
    });

При выборе значения для свойства minInstances учитывайте следующее:

  • Если Cloud Functions for Firebase масштабирует приложение выше значения minInstances, для каждого экземпляра, превышающего этот порог, будет выполняться холодный запуск.
  • Холодные запуски сильнее всего влияют на приложения с пиковым трафиком. Если в вашем приложении наблюдаются скачки трафика и вы установите для параметра minInstances достаточно высокое значение, чтобы при каждом увеличении трафика сокращалось количество холодных запусков, вы заметите значительное снижение задержки. Если у приложения постоянный трафик, холодный запуск вряд ли сильно повлияет на его эффективность.
  • Установка минимального количества экземпляров может быть целесообразной для рабочих сред, но обычно ее следует избегать в тестовых средах. Чтобы в тестовом проекте масштабирование выполнялось до нуля, но при этом в рабочем проекте сокращалось количество холодных запусков, можно задать minInstances на основе переменной среды FIREBASE_CONFIG:

    // Get Firebase project id from `FIREBASE_CONFIG` environment variable
    const envProjectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
    
    exports.renderProfilePage = functions
        .runWith({
          // Keep 5 instances warm for this latency-critical function
          // in production only. Default to 0 for test projects.
          minInstances: envProjectId === "my-production-project" ? 5 : 0,
        })
        .https.onRequest((req, res) => {
          // render some html
        });
    

Как ограничить максимальное количество экземпляров функции

Чтобы задать максимальное количество экземпляров в исходном коде функции, используйте метод runWith. Этот метод принимает объект JSON, соответствующий интерфейсу RuntimeOptions, который определяет значения для maxInstances. Например, эта функция устанавливает ограничение в 100 экземпляров, чтобы не перегружать гипотетическую устаревшую базу данных:

exports.mirrorOrdersToLegacyDatabase = functions
    .runWith({
      // Legacy database only supports 100 simultaneous connections
      maxInstances: 100,
    })
    .firestore.document("orders/{orderId}")
    .onWrite((change, context) => {
      // Connect to legacy database
    });

Если HTTP-функция масштабируется до лимита maxInstances, новые запросы помещаются в очередь на 30 секунд, а затем отклоняются с кодом ответа 429 Too Many Requests, если к этому времени не будет доступен ни один экземпляр.

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

Как настроить сервисный аккаунт

У сервисного аккаунта по умолчанию для функций первого поколения (PROJECT_ID@appspot.gserviceaccount.com, сервисный аккаунт App Engine по умолчанию) есть широкий набор разрешений, позволяющий взаимодействовать с другими сервисами Firebase и Google Cloud.

Вы можете переопределить сервисный аккаунт по умолчанию и ограничить функцию только необходимыми ресурсами. Для этого создайте специальный сервисный аккаунт и назначьте его нужной функции с помощью метода .runWith(). Этот метод принимает объект с параметрами конфигурации, включая свойство serviceAccount.

const functions = require("firebase-functions/v1");

exports.helloWorld = functions
    .runWith({
        // This function doesn't access other Firebase project resources, so it uses a limited service account.
        serviceAccount:
            "my-limited-access-sa@", // or prefer the full form: "my-limited-access-sa@my-project.iam.gserviceaccount.com"
    })
    .https.onRequest((request, response) => {
        response.send("Hello from Firebase!");
    });

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

В некоторых случаях для функций могут действовать особые требования к длительному значению тайм-аута или большому объему памяти. Эти значения можно задать в консоли Google Cloud или в исходном коде функции (только для Firebase).

Чтобы задать распределение памяти и время ожидания в исходном коде функций, используйте параметр runWith, добавленный в SDK Firebase для Cloud Functions 2.0.0. Этот параметр времени выполнения принимает объект JSON, соответствующий интерфейсу RuntimeOptions, который определяет значения для timeoutSeconds и memory. Например, эта функция хранилища использует 1 ГБ памяти и завершает работу по истечении 300 секунд:

exports.convertLargeFile = functions
    .runWith({
      // Ensure the function has enough memory and time
      // to process large files
      timeoutSeconds: 300,
      memory: "1GB",
    })
    .storage.object()
    .onFinalize((object) => {
      // Do some complicated things that take a lot of memory and time
    });

Максимальное значение для timeoutSeconds – 540, или 9 минут. Объем памяти, выделенной для функции, соответствует выделенному для нее процессору. Ниже приведен список допустимых значений для memory:

  • 128MB – 200 МГц
  • 256MB – 400 МГц
  • 512MB – 800 МГц
  • 1GB – 1,4 ГГц
  • 2GB – 2,4 ГГц
  • 4GB – 4,8 ГГц
  • 8GB – 4,8 ГГц

Чтобы задать распределение памяти и время ожидания в консоли Google Cloud, выполните следующие действия:

  1. В консоли Google Cloud выберите Cloud Functions в меню слева.
  2. Выберите функцию, нажав на ее название в списке.
  3. Нажмите на значок Изменить в верхнем меню.
  4. В раскрывающемся меню Выделенная память выберите объем памяти.
  5. Нажмите Ещё, чтобы открыть дополнительные параметры, и введите количество секунд в текстовом поле Тайм-аут.
  6. Нажмите Сохранить, чтобы обновить функцию.