Apps using 1st gen functions should consider migrating to 2nd gen using the instructions in this guide. 2nd gen functions use Cloud Run to provide better performance, better configuration, better monitoring, and more.
The examples in this document assume you're using JavaScript with CommonJS modules ( require style imports), but the same principles apply to JavaScript with ESM ( import … from style imports) and TypeScript.
миграционный процесс
1st gen and 2nd gen functions can coexist side-by-side in the same source file. This lets you migrate your codebase piece by piece, as you're ready. Note, however, that this mixing of packages does not work within a single, discrete function .
Мы рекомендуем переносить функции по одной, проводя тестирование и проверку перед продолжением.
Проверьте версии Firebase CLI и firebase-functions .
Убедитесь, что вы используете как минимум Firebase CLI версии 12.00 и firebase-functions версии 4.3.0 . Более новые версии будут поддерживать как первое, так и второе поколение.
Обновить импорты
2nd gen functions import from the v2 subpackage in the firebase-functions SDK. This different import path is all the Firebase CLI needs to determine whether to deploy your function code as a 1st or 2nd gen function.
Подпакет v2 имеет модульную структуру, и мы рекомендуем импортировать только тот конкретный модуль, который вам необходим.
Ранее: 1-е поколение
const functions = require("firebase-functions/v1");
После: 2-е поколение
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
Обновить определения триггеров
Поскольку SDK второго поколения предпочитает модульный импорт, обновите определения триггеров, чтобы отразить изменения в импорте, внесенные на предыдущем шаге.
The arguments passed to callbacks for some triggers have changed. In this example, note that the arguments to the onDocumentCreated callback have been consolidated into a single event object. Additionally, some triggers have convenient new configuration features, like the onRequest trigger's cors option.
Ранее: 1-е поколение
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
Сведите к минимуму усилия по переписыванию кода с помощью деструктуризации JavaScript.
If your functions have complex bodies that rely heavily on 1st gen context or provider-specific parameters (like message or snapshot ), you can use the 1st gen compatibility helpers built into the 2nd gen SDK.
The 2nd gen SDK automatically patches the event object with getters that match 1st gen signatures. This lets you use JavaScript destructuring to extract these properties directly in the handler signature, minimizing the need to rewrite your function logic.
Справочник по сопоставлению поставщиков
| Поставщик | Аргументы первого поколения | 2-е поколение, исправленная деструктуризация событий |
| Pub/Sub | (message, context) | ({ message, context }) => { ... } |
| Cloud Firestore | (snapshot, context) | ({ snapshot, context }) => { ... } |
| Cloud Storage | (object, context) | ({ object, context }) => { ... } |
| Realtime Database | (snapshot, context) | ({ snapshot, context }) => { ... } |
| Remote Config | (version, context) | ({ version, context }) => { ... } |
| Cloud Scheduler | (context) | ({ context }) => { ... } |
| Очередь задач | (data, context) | ({ data, context }) => { ... } |
До (1-е поколение):
export const myPubSubV1 = functions.pubsub.topic("my-topic").onPublish((message, context) => {
const data = message.json;
const eventId = context.eventId;
// ... rest of the logic
});
Новая альтернатива (2-е поколение с деструктуризацией):
import { onMessagePublished } from "firebase-functions/v2/pubsub";
export const myPubSubV2 = onMessagePublished("my-topic", ({ message, context }) => {
// No need to change the function body!
const data = message.json; // Uses v1 Message wrapper
const eventId = context.eventId; // Uses v1 EventContext map
// ... rest of the logic
});
Используйте параметризованную конфигурацию
2nd gen functions drop support for functions.config in favor of a more secure interface for defining configuration parameters declaratively inside your codebase. With the new params module, the CLI blocks deployment unless all parameters have a valid value, ensuring that a function isn't deployed with missing configuration.
Ранее: 1-е поколение
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {defineSecret} = require("firebase-functions/params");
// Define the secret parameter
const apiKey = defineSecret("API_KEY");
exports.getQuote = onRequest(
// make the secret available to this function
{ secrets: [apiKey] },
async (req, res) => {
// retrieve the value of the secret
const quote = await fetchMotivationalQuote(apiKey.value());
// ...
}
);
Если у вас уже есть конфигурация среды с functions.config , перенесите эту конфигурацию в рамках обновления до версии 2-го поколения.
API functions.config устарел и будет выведен из эксплуатации в марте 2027 года. После этой даты развертывание с использованием functions.config будет завершаться с ошибкой.
To prevent deployment failures, migrate your configuration to Cloud Secret Manager using the Firebase CLI. This is strongly recommended as the most efficient and secure way to migrate your configuration.
Экспорт конфигурации с помощью Firebase CLI
Используйте команду
config export, чтобы экспортировать существующую конфигурацию среды в новый секрет в Cloud Secret Manager:$ firebase functions:config:export i This command retrieves your Runtime Config values (accessed via functions.config()) and exports them as a Secret Manager secret. i Fetching your existing functions.config() from your project... ✔ Fetched your existing functions.config(). i Configuration to be exported: ⚠ This may contain sensitive data. Do not share this output. { ... } ✔ What would you like to name the new secret for your configuration? RUNTIME_CONFIG ✔ Created new secret version projects/project/secrets/RUNTIME_CONFIG/versions/1```Обновите код функции для привязки секретов.
To use configuration stored in the new secret in Cloud Secret Manager, use the
defineJsonSecretAPI in your function source. Also, make sure that secrets are bound to all functions that need them.До
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });После
const { onRequest } = require("firebase-functions/v2/https"); const { defineJsonSecret } = require("firebase-functions/params"); const config = defineJsonSecret("RUNTIME_CONFIG"); exports.myFunction = onRequest( // Bind secret to your function { secrets: [config] }, (req, res) => { // Access secret values via .value() const apiKey = config.value().someapi.key; // ... });Развертывание функций
Разверните обновленные функции, чтобы применить изменения и привязать секретные разрешения.
firebase deploy --only functions:<your-function-name>
Задайте параметры выполнения
Изменилась конфигурация параметров среды выполнения между 1-м и 2-м поколениями. Во 2-м поколении также добавлена новая возможность устанавливать параметры для всех функций.
Ранее: 1-е поколение
const functions = require("firebase-functions/v1");
exports.date = functions
.runWith({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
})
// locate function closest to users
.region("asia-northeast1")
.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions
// locate function closest to users and database
.region("asia-northeast1")
.firestore.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
После: 2-е поколение
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions/v2");
// locate all functions closest to users
setGlobalOptions({ region: "asia-northeast1" });
exports.date = onRequest({
// Keep 5 instances warm for this latency-critical function
minInstances: 5,
}, (req, res) => {
// ...
});
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
/* ... */
});
Обновить учетную запись службы по умолчанию (необязательно)
В то время как функции первого поколения используют учетную запись службы Google App Engine по умолчанию для авторизации доступа к API Firebase , функции второго поколения используют учетную запись службы Compute Engine по умолчанию. Это различие может привести к проблемам с разрешениями для функций, перенесенных на второе поколение, в случаях, когда вы предоставили специальные разрешения учетной записи службы первого поколения. Если вы не изменяли разрешения учетных записей служб, вы можете пропустить этот шаг.
The recommended solution is to explicitly assign the existing 1st gen App Engine default service account to functions that you want to migrate to 2nd gen, overriding the 2nd gen default. You can do this by making sure each migrated function sets the correct value for serviceAccountEmail :
const {onRequest} = require("firebase-functions/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
const {setGlobalOptions} = require("firebase-functions");
// Use the App Engine default service account for all functions
setGlobalOptions({serviceAccountEmail: '<my-project-number>@<wbr>appspot.gserviceaccount.com'});
// Now I use the App Engine default service account.
exports.date = onRequest({cors: true}, (req, res) => {
// ...
});
// I do too!
exports.uppercase = onDocumentCreated("my-collection/{docId}", (event) => {
// ...
});
Alternatively, you could make sure to modify the service account details to match all the necessary permissions on both the App Engine default service account (for 1st Gen) and the Compute Engine default service account (for 2nd Gen).
Используйте параллельное выполнение.
A significant advantage of 2nd gen functions is the ability of a single function instance to serve more than one request at once. This can dramatically reduce the number of cold starts experienced by end users. By default, concurrency is set at 80, but you can set it to any value from 1 to 1000:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
Настройка параллельного выполнения может повысить производительность и снизить стоимость функций. Подробнее о параллельном выполнении см. в разделе «Разрешить одновременные запросы» .
Проверка использования глобальных переменных
1st gen functions written without concurrency in mind might use global variables that are set and read on each request. When concurrency is enabled and a single instance starts handling multiple requests at once, this may introduce bugs in your function as concurrent requests start setting and reading global variables simultaneously.
В процессе обновления вы можете установить для своей функции значение ЦП gcf_gen1 и параметр concurrency равным 1, чтобы восстановить поведение первого поколения:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
However, this is not recommended as a long-term fix, because it forfeits the performance advantages of 2nd gen functions. Instead, audit usage of global variables in your functions, and remove these temporary settings when you're ready.
Перенаправьте трафик на новые функции второго поколения.
Как и при изменении региона или типа триггера функции , вам потребуется дать функции второго поколения новое имя и постепенно перенаправлять на неё трафик.
Невозможно обновить функцию с первого поколения до второго с тем же именем и запустить firebase deploy . Попытка сделать это приведет к ошибке:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Стратегия миграции зависит от типа триггера, используемого вашей функцией.
Перенесите вызываемые функции, очереди задач и HTTP-триггеры.
Эти триггеры являются прямыми вызовами. Поскольку функция второго поколения будет иметь новое имя (и новый URL для HTTP-триггеров), вы можете перенести трафик, обновив клиенты.
- Переименуйте функцию в своем коде (например, переименуйте
myCallableвmyCallableV2). - Разверните функцию. Теперь работают как функция первого, так и второго поколения.
- Обновите клиентский код или вызывающую функцию, чтобы она указывала на имя или URL-адрес новой функции второго поколения.
- После того, как весь трафик будет перенаправлен на новую функцию, удалите функцию первого поколения, используя команду
firebase functions:deleteв Firebase CLI.
Перенести фоновые триггеры
Background triggers (such as Pub/Sub , Cloud Firestore , and Cloud Storage triggers) respond to events in your project. To avoid missing any events during the transition, you must temporarily run both the 1st gen and 2nd gen functions side-by-side.
В течение переходного периода обе функции будут запускаться при одном и том же событии. Это означает, что ваша бизнес-логика будет выполняться дважды при каждом событии. Перед продолжением убедитесь, что ваша функция идемпотентна .
Добавьте функцию второго поколения рядом с функцией первого поколения, сохранив при этом существующую функцию первого поколения в вашем коде и добавив функцию второго поколения, которая будет прослушивать тот же источник событий.
import * as functions from "firebase-functions/v1"; import { onMessagePublished } from "firebase-functions/v2/pubsub"; // --- Existing 1st gen function --- export const myPubSub = functions.pubsub.topic("my-topic").onPublish((message, context) => { console.log("V1 handler running for event:", context.eventId); // ... existing v1 function logic ... }); // --- New v2 passthrough function --- export const myPubSubV2 = onMessagePublished("my-topic", async ({ message, context }) => { console.log("v2 handler triggering V1 for event:", context.eventId); // Call the v1 function's handler await myPubSub.run(message, context); });Выполните команду
firebase deploy. Обе функции теперь активны и прослушивают одни и те же события.Убедитесь, что функция второго поколения получает трафик. Отслеживайте журналы обеих функций. Убедитесь, что функция второго поколения вызывается для всех событий и что вызовы выполняются успешно.
Once you're confident that the function is performing correctly, move the actual business logic from the 1st gen function into the 2nd gen function's body. If you used the passthrough method, remove the call to
myPubSub.run().import * as functions from "firebase-functions/v1"; import { onMessagePublished } from "firebase-functions/v2/pubsub"; // --- Existing v1 function (to be removed next) --- export const myPubSub = functions.pubsub.topic("my-topic").onPublish((message, context) => { console.log("v1 handler running for event:", context.eventId); // ... existing v1 function logic ... }); // --- New v2 function with full logic --- export const myPubSubV2 = onMessagePublished("my-topic", ({ message, context }) => { console.log("v2 handler running for event:", context.eventId); // ... existing v1 function logic WAS MOVED HERE ... });Внедрите это изменение.
Удалите определение функции первого поколения из своего кода и выполните повторное развертывание. Интерфейс командной строки предложит вам удалить функцию первого поколения из Google Cloud .