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 Sie JavaScript mit CommonJS-Modulen (require-Importe) verwenden. Dieselben 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 verwendet werden. Dies ermöglicht die einfache Migration Schritt für Schritt, sobald Sie bereit sind. Wir empfehlen, jeweils nur eine Funktion zu migrieren und sie zu testen und zu prüfen, bevor Sie fortfahren.

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. Anhand dieses anderen Importpfads kann die Firebase-Befehlszeile ermitteln, ob der Funktionscode als Funktion der 1. oder 2. Generation bereitgestellt werden soll.

Das Unterpaket v2 ist modular. Wir empfehlen, nur das erforderliche 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, 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 Modul params blockiert die Befehlszeile die Bereitstellung, sofern alle Parameter keinen gültigen Wert haben. So wird verhindert, dass eine Funktion mit fehlender Konfiguration bereitgestellt wird.

Zum Unterpaket 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 von „functions.config“ zu exportieren.

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

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 Geheimnisparameter.

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 Gleichzeitigkeit aktiviert ist und eine einzelne Instanz damit beginnt, mehrere Anfragen gleichzeitig zu verarbeiten, kann dies zu Fehlern in der Funktion führen, da gleichzeitige Anfragen mit dem Festlegen und Lesen globaler Variablen beginnen.

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 bereit 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. Stellen Sie die Funktion so bereit, 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. Sie können die Funktion „2nd gen“ so umbenennen, dass sie mit dem Namen der Funktion der 1. Generation übereinstimmt.