Node.js-Funktionen der 1. Generation auf die 2. Generation umstellen

Für Apps, in denen derzeit Funktionen der 1. Generation verwendet werden, sollten Sie die Migration zur 2. Generation mithilfe der Anleitung in diesem Leitfaden in Betracht ziehen. Funktionen der 2. Generation nutzen Cloud Run für eine bessere Leistung, eine bessere Konfiguration und eine bessere Überwachung.

Bei den Beispielen auf dieser Seite wird davon ausgegangen, dass du JavaScript mit CommonJS-Modulen (require-Stilimporte) verwendest. Für JavaScript mit ESM (import … from-Stilimporten) und TypeScript gelten jedoch dieselben Prinzipien.

Der Migrationsvorgang

Funktionen der 1. Generation und der 2. Generation können in derselben Datei nebeneinander bestehen. So können Sie die Migration nach und nach vornehmen, sobald Sie bereit sind. Wir empfehlen, jeweils nur eine Funktion zu migrieren und vor dem Fortfahren Tests und Prüfungen durchzuführen.

Versionen der Firebase CLI und von firebase-function prüfen

Sie müssen mindestens Firebase CLI-Version 12.00 und firebase-functions-Version 4.3.0 verwenden. Alle neueren 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. Firebase CLI benötigt nur diesen Importpfad, um zu bestimmen, ob Ihr Funktionscode als Funktion der 1. oder 2. Generation bereitgestellt werden soll.

Das Teilpaket v2 ist modular. Wir empfehlen, nur das Modul zu importieren, das Sie benötigen.

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, aktualisieren Sie die Triggerdefinitionen, um die geänderten Importe aus dem vorherigen Schritt widerzuspiegeln.

Die Argumente, die bei einigen Triggern an Callbacks übergeben werden, haben sich geändert. In diesem Beispiel wurden die Argumente für den onDocumentCreated-Callback in einem einzigen event-Objekt zusammengefasst. Außerdem haben einige Trigger praktische neue Konfigurationsfunktionen, z. B. die Option cors des onRequest-Triggers.

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 für die deklarative Definition von Konfigurationsparametern in Ihrer Codebasis eingestellt. Mit dem neuen params-Modul blockiert die Befehlszeile die Bereitstellung, es sei denn, alle Parameter haben einen gültigen Wert. So wird verhindert, dass eine Funktion ohne Konfiguration bereitgestellt wird.

Zum Teilpaket params migrieren

Wenn Sie bisher die Umgebungskonfiguration mit functions.config verwendet haben, können Sie Ihre vorhandene Konfiguration zu einer parametrierten 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. Diese werden dann in einer dotenv-Datei gespeichert. Führen Sie firebase functions:config:export aus, um die Werte aus functions.config zu exportieren.

Für zusätzliche Sicherheit können Sie auch Parametertypen und Validierungsregeln festlegen.

Sonderfall: API-Schlüssel

Das params-Modul ist in Cloud Secret Manager eingebunden, das eine detaillierte Zugriffssteuerung für vertrauliche Werte wie API-Schlüssel bietet. Weitere Informationen finden Sie unter Secret-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 der Laufzeitoptionen hat sich zwischen der 1. und der 2. Generation geändert. Bei der 2. Generation können außerdem Optionen für alle Funktionen festgelegt werden.

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 besteht darin, dass eine einzelne Funktionsinstanz mehrere Anfragen gleichzeitig bedienen kann. So lässt sich die Anzahl der Kaltstarts für Endnutzer drastisch reduzieren. Standardmäßig ist die Gleichzeitigkeit auf 80 eingestellt, aber Sie können einen beliebigen Wert von 1 bis 1.000 festlegen:

const {onRequest} = require("firebase-functions/v2/https");

exports.date = onRequest({
    // set concurrency value
    concurrency: 500
  },
  (req, res) => {
    // ...
});

Durch die Optimierung der Parallelität lässt sich die Leistung verbessern und die Kosten von Funktionen senken. Weitere Informationen zur Gleichzeitigkeit finden Sie unter Gleichzeitige Anfragen zulassen.

Nutzung globaler Variablen prüfen

Funktionen der 1. Generation, die nicht für die Parallelität entwickelt wurden, können globale Variablen verwenden, 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 bei gleichzeitigen Anfragen globale Variablen gleichzeitig festgelegt und gelesen werden.

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 dadurch verloren gehen. Prüfen Sie stattdessen die Verwendung globaler Variablen in Ihren Funktionen und entfernen Sie diese temporären Einstellungen, sobald Sie fertig sind.

Traffic zu den neuen Funktionen der 2. Generation migrieren

Genau 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 nach und nach dorthin migrieren.

Es ist nicht möglich, eine Funktion mit demselben Namen von der 1. 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, prüfen Sie, 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, sollten Sie darauf achten, dass die Antwort auf einen Schreibvorgang zweimal, einmal von der Funktion der 1. Generation und einmal von der Funktion der 2. Generation, um auf diese Ereignisse zu reagieren, Ihre App in einem konsistenten Zustand bleibt.

  1. Benennen Sie die Funktion im Funktionscode um. Benennen Sie beispielsweise resizeImage in resizeImageSecondGen um.
  2. Binden Sie die Funktion so ein, dass sowohl die ursprüngliche Funktion der 1. Generation als auch die Funktion der 2. Generation ausgeführt werden.
    1. Bei aufrufbaren Funktionen, Task-Queues und HTTP-Triggern müssen Sie alle Clients auf die Funktion der 2. Generation verweisen. Aktualisieren Sie dazu den Clientcode mit dem Namen oder der URL der Funktion der 2. Generation.
    2. Mit Hintergrundtriggern reagieren sowohl die Funktionen der 1. Generation als auch der 2. Generation sofort nach der Bereitstellung auf jedes Ereignis.
  3. Wenn der gesamte Traffic migriert wurde, löschen Sie die Funktion der 1. Generation mit dem Befehl firebase functions:delete der Firebase CLI.
    1. Optional können Sie die Funktion der 2. Generation in den Namen der Funktion der 1. Generation umbenennen.