Migrieren auf Version 4 des Node.js-Programmiermodells für Azure Functions

In diesem Artikel werden die Unterschiede zwischen Version 3 und Version 4 des Node.js-Programmiermodells sowie das Upgrade einer vorhandenen v3-App erläutert. Wenn Sie eine neue v4-App erstellen möchten, anstatt ein Upgrade einer vorhandenen v3-App auszuführen, lesen Sie das Tutorial für Visual Studio Code (VS Code) oder Azure Functions Core Tools. In diesem Artikel werden „Tipp“-Warnungen verwendet, um die wichtigsten konkreten Aktionen, die Sie zum Upgrade Ihrer App ergreifen sollten, hervorzuheben.

Version 4 bietet Node.js-Entwicklern die folgenden Nutzen:

  • Stellen Sie eine vertraute und intuitive Benutzeroberfläche für Node.js-Entwickler bereit.
  • Stellen Sie eine flexible Dateistruktur mit Unterstützung für vollständige Anpassung bereit.
  • Wechseln Sie zu einem codezentrierten Ansatz zum Definieren der Funktionskonfiguration.

Überlegungen

  • Das Node.js-Programmiermodell sollte nicht mit der Azure Functions-Runtime verwechselt werden:
    • Programmiermodell: Definiert, wie Sie Ihren Code erstellen und ist spezifisch für JavaScript und TypeScript.
    • Runtime: Definiert das zugrunde liegende Verhalten von Azure Functions und wird für alle Sprachen gemeinsam verwendet.
  • Die Programmiermodellversion ist eng an die Version des @azure/functions-npm-Pakets gebunden. Sie wird unabhängig von der Runtime mit Versionsangaben versehen. Sowohl die Runtime als auch das Programmiermodell verwenden die Angabe „4“ als neueste Hauptversion, aber das ist Zufall.
  • Sie können die v3- und v4-Programmiermodelle nicht in derselben Funktions-App kombinieren. Sobald Sie eine v4-Funktion in Ihrer App registrieren, werden alle in function.json-Dateien registrierten v3-Funktionen ignoriert.

Anforderungen

Version 4 des Node.js-Programmiermodells erfordert die folgenden Mindestversionen:

Einbinden des npm-Pakets

In V4 enthält das @azure/functions-npm-Paket den primären Quellcode, der das Node.js-Programmiermodell unterstützt. In früheren Versionen wurde dieser Code direkt in Azure ausgeliefert, und das npm-Paket enthielt nur die TypeScript-Typen. Sie müssen dieses Paket jetzt sowohl für TypeScript- als auch für JavaScript-Apps einschließen. Sie können das Paket für vorhandene v3-Apps einschließen, aber es ist nicht erforderlich.

Tipp

Stellen Sie sicher, dass das @azure/functions-Paket im dependencies-Abschnitt (nicht devDependencies) Ihrer package.json-Datei aufgeführt wird. Sie können V4 mit dem folgenden Befehl installieren:

npm install @azure/functions

Festlegen des App-Einstiegspunkts

In v4 des Programmiermodells können Sie Ihren Code beliebig strukturieren. Die einzigen Dateien, die Sie am Stamm Ihrer App benötigen, sind host.json und package.json.

Andernfalls definieren Sie die Dateistruktur, indem Sie das main-Feld in Ihrer Datei package.json festlegen. Sie können das main-Feld auf eine einzelne Datei oder mithilfe eines Globmusters auf mehrere Dateien festlegen. Die folgende Tabelle zeigt Beispielwerte für das main Feld:

Beispiel BESCHREIBUNG
src/index.js Registrieren sie Funktionen aus einer einzelnen Stammdatei.
src/functions/*.js Registrieren Sie jede Funktion aus einer eigenen Datei.
src/{index.js,functions/*.js} Eine Kombination, in der Sie jede Funktion aus einer eigenen Datei registrieren, aber dennoch über eine Stammdatei für allgemeinen Code auf App-Ebene verfügen.
Beispiel BESCHREIBUNG
dist/src/index.js Registrieren sie Funktionen aus einer einzelnen Stammdatei.
dist/src/functions/*.js Registrieren Sie jede Funktion aus einer eigenen Datei.
dist/src/{index.js,functions/*.js} Eine Kombination, in der Sie jede Funktion aus einer eigenen Datei registrieren, aber dennoch über eine Stammdatei für allgemeinen Code auf App-Ebene verfügen.

Tipp

Stellen Sie sicher, dass Sie ein main-Feld in Ihrer Datei package.json definieren.

Ändern der Reihenfolge der Argumente

Die Triggereingabe ist jetzt das erste Argument für den Funktionshandler anstelle des Aufrufkontexts. Der Aufrufkontext, jetzt das zweite Argument, wurde in V4 vereinfacht und ist nicht so erforderlich wie die Triggereingabe. Er kann weggelassen werden, wenn Sie ihn nicht verwenden.

Tipp

Ändern Sie die Reihenfolge Ihrer Argumente. Wenn Sie beispielsweise einen HTTP-Trigger verwenden, ändern Sie (context, request) in (request, context) oder nur (request), wenn Sie den Kontext nicht verwenden.

Definieren Ihrer Funktion in Code

Sie müssen diese separaten funktions.json-Konfigurationsdateien nicht mehr erstellen und verwalten. Sie können Ihre Funktionen jetzt vollständig in Ihren TypeScript- oder JavaScript-Dateien definieren. Darüber hinaus verfügen viele Eigenschaften jetzt über Standardwerte, sodass Sie nicht jedes Mal Werte angeben müssen.

const { app } = require('@azure/functions');

app.http('httpTrigger1', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: async (request, context) => {
        context.log(`Http function processed request for url "${request.url}"`);

        const name = request.query.get('name') || (await request.text()) || 'world';

        return { body: `Hello, ${name}!` };
    },
});
import { app, HttpRequest, HttpResponseInit, InvocationContext } from '@azure/functions';

export async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
    context.log(`Http function processed request for url "${request.url}"`);

    const name = request.query.get('name') || (await request.text()) || 'world';

    return { body: `Hello, ${name}!` };
}

app.http('httpTrigger1', {
    methods: ['GET', 'POST'],
    authLevel: 'anonymous',
    handler: httpTrigger1,
});

Tipp

Verschieben Sie die Konfiguration aus Ihrer function.json-Datei in Ihren Code. Der Typ des Triggers entspricht einer Methode für das app-Objekt im neuen Modell. Wenn Sie beispielsweise einen httpTrigger-Typ in function.json verwenden, rufen Sie app.http() in Ihrem Code auf, um die Funktion zu registrieren. Wenn Sie timerTrigger verwenden, rufen Sie app.timer() auf.

Überprüfen der Verwendung des Kontexts

In V4 wird das context-Objekt vereinfacht, um Dopplungen zu reduzieren und das Schreiben von Komponententests zu vereinfachen. Beispielsweise haben wir die primäre Eingabe und Ausgabe optimiert, sodass auf sie nur als Argument und Rückgabewert Ihres Funktionshandlers zugegriffen wird.

Sie können nicht mehr auf die primäre Eingabe und Ausgabe für das context-Objekt zugreifen. Sie müssen jedoch weiterhin auf sekundäre Eingaben und Ausgaben für das context-Objekt zugreifen. Weitere Informationen zu sekundären Eingaben und Ausgaben finden Sie im Entwicklerleitfaden für Node.js.

Abrufen der primären Eingabe als Argument

Die primäre Eingabe wird auch als Trigger bezeichnet und ist die einzige erforderliche Eingabe oder Ausgabe. Sie müssen genau einen Trigger verwenden.

Version 4 unterstützt nur eine Möglichkeit, die Triggereingabe abzurufen, nämlich als erstes Argument:

async function httpTrigger1(request, context) {
  const onlyOption = request;
async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
  const onlyOption = request;

Tipp

Stellen Sie sicher, dass Sie nicht context.req oder context.bindings verwenden, um die Eingabe abzurufen.

Festlegen der primären Ausgabe als Rückgabewert

Version 4 unterstützt nur eine Möglichkeit, die primäre Ausgabe festzulegen, nämlich über den Rückgabewert:

return { 
  body: `Hello, ${name}!` 
};
async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
    // ...
    return { 
      body: `Hello, ${name}!` 
    };
}

Tipp

Stellen Sie sicher, dass Sie die Ausgabe immer im Funktionshandler zurückgeben, anstatt sie mit dem context-Objekt festzulegen.

Kontextprotokollierung

In v4 wurden Protokollierungsmethoden in das Stammobjekt context verschoben, wie im folgenden Beispiel gezeigt. Weitere Informationen zur Protokollierung finden Sie im Node.js-Entwicklerhandbuch.

context.log('This is an info log');
context.error('This is an error');
context.warn('This is an error');

Erstellen eines Testkontexts

Version 3 unterstützt das Erstellen eines Aufrufkontexts außerhalb der Azure Functions-Runtime nicht, sodass das Erstellen von Komponententests schwierig sein kann. Mit Version 4 können Sie eine Instanz des Aufrufkontexts erstellen, obwohl die Informationen während der Tests nicht detailliert sind, es sei denn, Sie fügen sie selbst hinzu.

const testInvocationContext = new InvocationContext({
  functionName: 'testFunctionName',
  invocationId: 'testInvocationId'
});

Überprüfen der Verwendung von HTTP-Typen

Die HTTP-Anforderungs- und -Antworttypen sind jetzt eine Teilmenge des Abrufstandards. Sie sind nicht mehr typspezifisch für Azure Functions.

Die Typen verwenden das undici-Paket in Node.js. Das Paket folgt dem Abrufstandard und wird derzeit in Node.js Core integriert.

HttpRequest

  • Text: Sie können auf den Textkörper mit einer Methode zugreifen, die für den gewünschten Typ spezifisch ist:

    const body = await request.text();
    const body = await request.json();
    const body = await request.formData();
    const body = await request.arrayBuffer();
    const body = await request.blob();
    
  • Header:

    const header = request.headers.get('content-type');
    
  • Abfrageparameter:

    const name = request.query.get('name');
    

HttpResponse

  • Status:

    return { status: 200 };
    
  • Text:

    Verwenden Sie die Eigenschaft, um die body meisten Typen wie ein string oder Buffer:

    return { body: "Hello, world!" };
    

    Verwenden Sie die jsonBody Eigenschaft für die einfachste Möglichkeit, eine JSON-Antwort zurückzugeben:

    return { jsonBody: { hello: "world" } };
    
  • Header. Sie können den Header auf zwei Arten festlegen, je nachdem, ob Sie die HttpResponse-Klasse oder die HttpResponseInit-Schnittstelle verwenden:

    const response = new HttpResponse();
    response.headers.set('content-type', 'application/json');
    return response;
    
    return {
      headers: { 'content-type': 'application/json' }
    };
    

Tipp

Aktualisieren Sie die gesamte Programmlogik mithilfe der HTTP-Anforderungs- oder Antworttypen so, dass sie den neuen Methoden entspricht.

Tipp

Aktualisieren Sie die gesamte Programmlogik mithilfe der HTTP-Anforderungs- oder Antworttypen so, dass sie den neuen Methoden entspricht. Sie sollten TypeScript-Buildfehler erhalten, um festzustellen, ob Sie alte Methoden verwenden.

Problembehandlung

Weitere Informationen finden Sie im Node.js-Leitfaden zur Problembehandlung.