Apps, die Funktionen der 1. Generation verwenden, sollten gemäß der Anleitung in diesem Leitfaden zur 2. Generation migriert werden. Funktionen der 2. Generation verwenden Cloud Run, um eine bessere Leistung, bessere Konfiguration, besseres Monitoring und mehr zu bieten.
In den Beispielen auf dieser Seite wird davon ausgegangen, dass Sie JavaScript mit CommonJS-Modulen (require
-Importe) verwenden. Die gleichen Prinzipien gelten jedoch auch für JavaScript mit ESM (import … from
-Importe) und TypeScript.
Der Migrationsvorgang
Funktionen der 1. und 2. Generation können in derselben Datei nebeneinander vorhanden sein. So können Sie die Migration ganz einfach nach und nach durchführen, wenn Sie bereit sind. Wir empfehlen, jeweils nur eine Funktion zu migrieren und vor dem Fortfahren Tests und Überprüfungen durchzuführen.
Versionen von Firebase CLI und firebase-function
prüfen
Achten Sie darauf, dass Sie mindestens die Firebase CLI-Version 12.00
und die firebase-functions
-Version 4.3.0
verwenden. Neuere Versionen unterstützen sowohl die 2. 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-CLI 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 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 im SDK der 2. Generation modulare Importe bevorzugt werden, müssen Sie die Triggerdefinitionen entsprechend den geänderten Importen aus dem vorherigen Schritt aktualisieren.
Die Argumente, die an Callbacks für einige Trigger übergeben werden, haben sich geändert. In diesem Beispiel wurden die Argumente für den onDocumentCreated
-Callback in einem einzelnen event
-Objekt zusammengefasst. Außerdem haben 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) => {
/* ... */
});
Parametrisierte Konfiguration verwenden
Bei Funktionen der 2. Generation wird die Unterstützung für functions.config
zugunsten einer sichereren Schnittstelle zum deklarativen Definieren von Konfigurationsparametern in Ihrem Code eingestellt. Mit dem neuen params
-Modul blockiert die CLI die Bereitstellung, sofern nicht alle Parameter einen gültigen Wert haben. So wird verhindert, dass eine Funktion ohne Konfiguration bereitgestellt wird.
Zum Unterpaket params
migrieren
Wenn Sie die Umgebungskonfiguration mit functions.config
verwendet haben, können Sie Ihre vorhandene Konfiguration zu einer parametrisierten Konfiguration migrieren.
Vorher: 1. Generation
const functions = require("firebase-functions/v1");
exports.date = functions.https.onRequest((req, res) => {
const date = new Date();
const formattedDate =
date.toLocaleDateString(functions.config().dateformat);
// ...
});
Nachher: 2. Generation
const {onRequest} = require("firebase-functions/v2/https");
const {defineString} = require("firebase-functions/params");
const dateFormat = defineString("DATE_FORMAT");
exports.date = onRequest((req, res) => {
const date = new Date();
const formattedDate = date.toLocaleDateString(dateFormat.value());
// ...
});
Parameterwerte festlegen
Beim ersten Bereitstellen werden Sie von der Firebase CLI aufgefordert, alle Parameterwerte anzugeben. Die Werte werden in einer dotenv-Datei gespeichert. Führen Sie firebase functions:config:export
aus, um die Werte von „functions.config“ zu exportieren.
Für zusätzliche Sicherheit können Sie auch Parametertypen und Validierungsregeln angeben.
Sonderfall: API-Schlüssel
Das Modul params
lässt sich in Cloud Secret Manager einbinden, das eine detaillierte Zugriffssteuerung für vertrauliche Werte wie API-Schlüssel bietet. Weitere Informationen finden Sie unter Geheime Parameter.
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());
// ...
}
);
Laufzeitoptionen festlegen
Die Konfiguration von Laufzeitoptionen hat sich zwischen der 1. und der 2. Generation geändert. In der 2. Generation wurde außerdem eine neue Funktion zum Festlegen von Optionen für alle Funktionen hinzugefügt.
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) => {
/* ... */
});
Gleichzeitigkeit verwenden
Ein wesentlicher Vorteil von Funktionen der 2. Generation ist die Möglichkeit, dass eine einzelne Funktionsinstanz mehrere Anfragen gleichzeitig verarbeiten kann. So kann die Anzahl der Kaltstarts für Endnutzer erheblich 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 das Optimieren der Parallelität kann die Leistung verbessert und die Kosten für Funktionen gesenkt werden. Weitere Informationen zur Gleichzeitigkeit
Verwendung globaler Variablen prüfen
Funktionen der 1. Generation, die nicht für die gleichzeitige Ausführung konzipiert wurden, verwenden möglicherweise globale Variablen, die bei jeder Anfrage festgelegt und gelesen werden. Wenn die Nebenläufigkeit aktiviert ist und eine einzelne Instanz beginnt, mehrere Anfragen gleichzeitig zu verarbeiten, kann dies zu Fehlern in Ihrer Funktion führen, da gleichzeitige Anfragen globale Variablen gleichzeitig festlegen und lesen.
Während des Upgrades können Sie die CPU Ihrer Funktion auf gcf_gen1
und concurrency
auf 1 festlegen, 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
Genau wie beim Ändern der Region oder des Triggertyps einer Funktion müssen Sie der 2nd gen-Funktion einen neuen Namen geben und den Traffic langsam darauf umstellen.
Es ist nicht möglich, eine Funktion der 1. Generation mit demselben Namen auf die 2. Generation zu aktualisieren und firebase deploy
auszuführen. Andernfalls wird folgender Fehler ausgegeben:
Upgrading from GCFv1 to GCFv2 is not yet supported. Please delete your old function or wait for this feature to be ready.
Bevor Sie diese Schritte ausführen, sollten Sie prüfen, ob Ihre Funktion idempotent ist, da während der Änderung sowohl die neue als auch die alte Version Ihrer Funktion gleichzeitig ausgeführt werden. Wenn Sie beispielsweise eine Funktion der 1. Generation haben, die auf Schreibereignisse in Firestore reagiert, muss Ihre App in einem konsistenten Zustand bleiben, wenn zweimal auf ein Schreibereignis reagiert wird, einmal von der Funktion der 1. Generation und einmal von der Funktion der 2. Generation.
- Benennen Sie die Funktion im Code Ihrer Funktionen um. Benennen Sie beispielsweise
resizeImage
inresizeImageSecondGen
um. - Stellen Sie die Funktion bereit, sodass sowohl die ursprüngliche Funktion der 1. Generation als auch die Funktion der 2. Generation ausgeführt werden.
- Bei aufrufbaren, Task Queue- und HTTP-Triggern müssen Sie alle Clients auf die Funktion der 2. Generation verweisen, indem Sie den Clientcode mit dem Namen oder der URL der Funktion der 2. Generation aktualisieren.
- Bei Hintergrundtriggern reagieren sowohl die Funktionen der 1. als auch der 2. Generation nach der Bereitstellung sofort auf jedes Ereignis.
- Wenn der gesamte Traffic migriert wurde, löschen Sie die Funktion der 1. Generation mit dem Befehl
firebase functions:delete
der Firebase CLI.- Benennen Sie die Funktion der 2. Generation optional so um, dass sie dem Namen der Funktion der 1. Generation entspricht.