Apps, die Funktionen der 1. Generation verwenden, sollten gemäß der Anleitung in diesem Leitfaden zu Funktionen der 2. Generation migriert werden. Funktionen der 2. Generation verwenden Cloud Run, um eine bessere Leistung, eine bessere Konfiguration, ein besseres Monitoring und mehr zu bieten.
In den Beispielen in diesem Dokument wird davon ausgegangen, dass Sie JavaScript mit CommonJS-Modulen (Importe im require-Stil) verwenden. Dieselben Prinzipien gelten jedoch auch für JavaScript mit ESM (Importe im import … from-Stil) und TypeScript.
Der Migrationsvorgang
Funktionen der 1. Generation und der 2. Generation können in derselben Quelldatei nebeneinander existieren. So können Sie Ihre Codebasis nach und nach migrieren, wenn Sie bereit sind. Beachten Sie jedoch, dass diese Mischung von Paketen nicht innerhalb einer einzelnen, diskreten Funktion funktioniert.
Wir empfehlen, jeweils eine Funktion zu migrieren und vor dem Fortfahren Tests und Verifizierungen durchzuführen.
Firebase-Befehlszeile und firebase-functions-Versionen prüfen
Achten Sie darauf, dass Sie mindestens die Firebase-CLI-Version 12.00 und die firebase-functions-Version 4.3.0 verwenden. Alle neueren Versionen unterstützen sowohl die 2. Generation als auch die 1. Generation.
Importe aktualisieren
Funktionen der 2. Generation werden aus dem Unterpaket v2 im firebase-functions SDK importiert. Dieser andere Importpfad ist alles, was die Firebase-Befehlszeile benötigt, um zu bestimmen, ob Ihr Funktionscode als Funktion der 1. oder 2. Generation bereitgestellt werden soll.
Das Unterpaket v2 ist modular aufgebaut. Wir empfehlen, nur das jeweils benötigte Modul zu importieren.
Vorher: 1. Generation
const functions = require("firebase-functions/v1");
Nachher: 2. Generation
// explicitly import each trigger
const {onRequest} = require("firebase-functions/v2/https");
const {onDocumentCreated} = require("firebase-functions/v2/firestore");
Triggerdefinitionen aktualisieren
Da das SDK der 2. Generation modulare Importe bevorzugt, müssen Sie die Triggerdefinitionen aktualisieren, um die geänderten Importe aus dem vorherigen Schritt widerzuspiegeln.
Die Argumente, die für einige Trigger an Callbacks übergeben werden, haben sich geändert. In diesem Beispiel wurden die Argumente für den Callback onDocumentCreated in einem einzigen event-Objekt zusammengefasst. Außerdem bieten einige Trigger praktische neue Konfigurationsfunktionen, z. B. die Option cors des Triggers onRequest.
Vorher: 1. Generation
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
// ...
});
exports.uppercase = functions.firestore
.document("my-collection/{docId}")
.onCreate((change, context) => {
// ...
});
Nachher: 2. Generation
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) => {
/* ... */
});
Umschreibungsaufwand mit JavaScript-Destrukturierung minimieren
Wenn Ihre Funktionen komplexe Bodies haben, die stark auf Kontext der 1. Generation oder anbieterspezifische Parameter (wie message oder snapshot) angewiesen sind, können Sie die Kompatibilitätshelfer der 1. Generation verwenden, die in das SDK der 2. Generation integriert sind.
Das SDK der 2. Generation patcht das Ereignisobjekt automatisch mit Gettern, die mit den Signaturen der 1. Generation übereinstimmen. So können Sie diese Attribute mithilfe von JavaScript-Destrukturierung direkt in der Handler-Signatur extrahieren und müssen die Funktionslogik nicht neu schreiben.
Referenz zur Anbieterzuordnung
| Provider | Argumente der 1. Generation | Destrukturierung von gepatchten Ereignissen der 2. Generation |
| 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 }) => { ... }
|
| Aufgabenwarteschlange | (data, context)
|
({ data, context }) => { ... }
|
Vorher (1. Generation):
export const myPubSubV1 = functions.pubsub.topic("my-topic").onPublish((message, context) => {
const data = message.json;
const eventId = context.eventId;
// ... rest of the logic
});
Neue Alternative (2. Generation mit Destrukturierung):
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
});
Parametrisierte Konfiguration verwenden
Funktionen der 2. Generation unterstützen functions.config nicht mehr. Stattdessen wird eine sicherere Schnittstelle zum deklarativen Definieren von Konfigurationsparametern in Ihrer Codebasis verwendet.
Mit dem neuen params-Modul blockiert die Befehlszeile die Bereitstellung, wenn nicht alle Parameter einen gültigen Wert haben. So wird sichergestellt, dass eine Funktion nicht mit fehlender Konfiguration bereitgestellt wird.
Vorher: 1. Generation
const functions = require("firebase-functions/v1");
exports.getQuote = functions.https.onRequest(async (req, res) => {
const quote = await fetchMotivationalQuote(functions.config().apiKey);
// ...
});
Nachher: 2. Generation
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());
// ...
}
);
Wenn Sie eine vorhandene Umgebungskonfiguration mit functions.config haben, migrieren Sie diese Konfiguration im Rahmen des Upgrades auf die 2. Generation.
Die functions.config API wird eingestellt und im März 2027 außer Betrieb genommen.
Nach diesem Datum schlagen Bereitstellungen mit functions.config fehl.
Migrieren Sie Ihre Konfiguration mit der Firebase-Befehlszeile zu Cloud Secret Manager, um Bereitstellungsfehler zu vermeiden. Dies wird dringend empfohlen, da es die effizienteste und sicherste Methode zur Migration Ihrer Konfiguration ist.
Konfiguration mit der Firebase-Befehlszeile exportieren
Verwenden Sie den Befehl
config export, um Ihre vorhandene Umgebungskonfiguration in ein neues Secret in Cloud Secret Manager zu exportieren:$ 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```Funktionscode aktualisieren, um Secrets zu binden
Wenn Sie die im neuen Secret in Cloud Secret Manager gespeicherte Konfiguration verwenden möchten, verwenden Sie die
defineJsonSecretAPI in Ihrer Funktionsquelle. Achten Sie außerdem darauf, dass Secrets an alle Funktionen gebunden sind, die sie benötigen.Vorher
const functions = require("firebase-functions/v1"); exports.myFunction = functions.https.onRequest((req, res) => { const apiKey = functions.config().someapi.key; // ... });Nachher
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; // ... });Funktionen bereitstellen
Stellen Sie die aktualisierten Funktionen bereit, um die Änderungen zu übernehmen und die Secret-Berechtigungen zu binden.
firebase deploy --only functions:<your-function-name>
Laufzeitoptionen festlegen
Die Konfiguration der Laufzeitoptionen hat sich zwischen der 1. und 2. Generation geändert. In der 2. Generation gibt es außerdem eine neue Funktion, mit der Sie Optionen für alle Funktionen festlegen können.
Vorher: 1. Generation
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) => {
// ...
});
Nachher: 2. Generation
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) => {
/* ... */
});
Standarddienstkonto aktualisieren (optional)
Während Funktionen der 1. Generation das Standarddienstkonto Google App Engine verwenden, um den Zugriff auf Firebase-APIs zu autorisieren, verwenden Funktionen der 2. Generation das Standarddienstkonto Compute Engine. Dieser Unterschied kann zu Berechtigungsproblemen bei Funktionen führen, die zur 2. Generation migriert wurden, wenn Sie dem Dienstkonto der 1. Generation spezielle Berechtigungen gewährt haben. Wenn Sie keine Dienstkontoberechtigungen geändert haben, können Sie diesen Schritt überspringen.
Die empfohlene Lösung besteht darin, das vorhandene Standarddienstkonto App Engine der 1. Generation explizit Funktionen zuzuweisen, die Sie zur 2. Generation migrieren möchten, und so den Standardwert der 2. Generation zu überschreiben. Dazu müssen Sie dafür sorgen, dass für jede migrierte Funktion der richtige Wert für serviceAccountEmail festgelegt ist:
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) => {
// ...
});
Alternativ können Sie die Dienstkontodetails so ändern, dass sie alle erforderlichen Berechtigungen sowohl für das Standarddienstkonto App Engine (für die 1. Generation) als auch für das Standarddienstkonto Compute Engine (für die 2. Generation) enthalten.
Nebenläufigkeit verwenden
Ein wesentlicher Vorteil von Funktionen der 2. Generation ist die Möglichkeit, dass eine einzelne Funktionsinstanz mehrere Anfragen gleichzeitig verarbeiten kann. Dadurch kann die Anzahl der Kaltstarts, die Endnutzer erleben, drastisch reduziert werden. Standardmäßig ist die Nebenläufigkeit auf 80 festgelegt. Sie können sie jedoch auf einen beliebigen Wert zwischen 1 und 1.000 festlegen:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// set concurrency value
concurrency: 500
},
(req, res) => {
// ...
});
Durch die Optimierung der Nebenläufigkeit können Sie die Leistung verbessern und die Kosten für Funktionen senken. Weitere Informationen zur Gleichzeitigkeit finden Sie unter Gleichzeitige Anfragen zulassen.
Verwendung globaler Variablen prüfen
Funktionen der 1. Generation, die ohne Berücksichtigung der Nebenläufigkeit geschrieben wurden, verwenden möglicherweise globale Variablen, die bei jeder Anfrage festgelegt und gelesen werden. Wenn die Nebenläufigkeit aktiviert ist und eine einzelne Instanz mehrere Anfragen gleichzeitig verarbeitet, kann dies zu Fehlern in Ihrer Funktion führen, da gleichzeitige Anfragen gleichzeitig globale Variablen festlegen und lesen.
Während des Upgrades können Sie die CPU Ihrer Funktion auf gcf_gen1 und concurrency auf 1 setzen, um das Verhalten der 1. Generation wiederherzustellen:
const {onRequest} = require("firebase-functions/v2/https");
exports.date = onRequest({
// TEMPORARY FIX: remove concurrency
cpu: "gcf_gen1",
concurrency: 1
},
(req, res) => {
// ...
});
Dies wird jedoch nicht als langfristige Lösung empfohlen, da die Leistungsvorteile von Funktionen der 2. Generation verloren gehen. Prüfen Sie stattdessen die Verwendung globaler Variablen in Ihren Funktionen und entfernen Sie diese temporären Einstellungen, wenn Sie bereit sind.
Traffic zu den neuen 2nd gen-Funktionen migrieren
Wie beim Ändern der Region oder des Triggertyps einer Funktion müssen Sie der Funktion der 2. Generation einen neuen Namen geben und den Traffic langsam dorthin migrieren.
Es ist nicht möglich, eine Funktion der 1. Generation auf die 2. Generation mit demselben Namen und derselben Laufzeit firebase deploy zu aktualisieren. Dies führt zu folgendem Fehler:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Die Migrationsstrategie hängt vom Triggertyp ab, den Ihre Funktion verwendet.
Aufrufbare, Aufgabenwarteschlangen- und HTTP-Trigger migrieren
Diese Trigger sind direkte Aufrufe. Da die Funktion der 2. Generation einen neuen Namen (und eine neue URL für HTTP-Trigger) hat, können Sie den Traffic migrieren, indem Sie die Clients aktualisieren.
- Benennen Sie die Funktion in Ihrem Code um (z. B.
myCallableinmyCallableV2). - Funktion bereitstellen Sowohl die Funktionen der 1. Generation als auch die der 2. Generation werden jetzt ausgeführt.
- Aktualisieren Sie Ihren Clientcode oder Aufrufer, sodass er auf den Namen oder die URL der neuen Funktion der 2. Generation verweist.
- Sobald der gesamte Traffic auf die neue Funktion umgeleitet wurde, löschen Sie die Funktion der 1. Generation mit dem Befehl
firebase functions:deleteder Firebase-Befehlszeile.
Hintergrundtrigger migrieren
Hintergrundtrigger (z. B. Pub/Sub-, Cloud Firestore- und Cloud Storage-Trigger) reagieren auf Ereignisse in Ihrem Projekt. Damit während der Umstellung keine Ereignisse verloren gehen, müssen Sie die Funktionen der 1. und 2. Generation vorübergehend parallel ausführen.
Während der Übergangsphase werden beide Funktionen durch dasselbe Ereignis ausgelöst. Das bedeutet, dass Ihre Geschäftslogik zweimal pro Ereignis ausgeführt wird. Achten Sie darauf, dass Ihre Funktion idempotent ist, bevor Sie fortfahren.
Fügen Sie die Funktion der 2. Generation neben der Funktion der 1. Generation hinzu. Behalten Sie die vorhandene Funktion der 1. Generation in Ihrem Code bei und fügen Sie die Funktion der 2. Generation hinzu, die auf dieselbe Ereignisquelle lauscht.
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); });Führen Sie
firebase deployaus. Beide Funktionen sind jetzt aktiv und überwachen dieselben Ereignisse.Prüfen Sie, ob die Funktion der 2. Generation Traffic empfängt. Behalten Sie die Logs für beide Funktionen im Blick. Achten Sie darauf, dass die Funktion der 2. Generation für alle Ereignisse aufgerufen wird und die Aufrufe erfolgreich sind.
Wenn Sie sicher sind, dass die Funktion korrekt ausgeführt wird, verschieben Sie die eigentliche Geschäftslogik von der Funktion der 1. Generation in den Text der Funktion der 2. Generation. Wenn Sie die Passthrough-Methode verwendet haben, entfernen Sie den Aufruf von
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 ... });Stellen Sie diese Änderung bereit.
Entfernen Sie die Funktionsdefinition der 1. Generation aus Ihrem Code und stellen Sie ihn noch einmal bereit. Die Befehlszeile fordert Sie auf, die Funktion der 1. Generation aus Google Cloud zu löschen.