Compartilhar via


Migrar para o modelo de programação Node.js versão 4 para Azure Functions

Este artigo discute as diferenças entre a versão 3 e a versão 4 do modelo de programação Node.js e como atualizar um aplicativo v3 existente. Para criar um aplicativo v4 em vez de atualizar um aplicativo v3 atual, confira o tutorial do Visual Studio Code (VS Code) ou do Azure Functions Core Tools. Este artigo usa alertas de "dica" para destacar as ações concretas mais importantes que você deve realizar para atualizar o aplicativo. A versão 4 foi projetada para fornecer aos desenvolvedores do Node.js os seguintes benefícios:

  • Fornecer uma experiência familiar e intuitiva aos desenvolvedores do Node.js.
  • Tornar a estrutura de arquivos flexível com suporte para a personalização completa.
  • Alternar para uma abordagem centrada em código para definir a configuração da função.

Considerações

  • O modelo de programação Node.js não deve ser confundido com o runtime do Azure Functions:
    • Modelo de programação: define como você cria o código e é específico de JavaScript e TypeScript.
    • Runtime: define o comportamento do Azure Functions e é compartilhado em todas as linguagens.
  • A versão do modelo de programação está estritamente vinculada à versão do pacote npm @azure/functions. Essa versão é criada de maneira independente do runtime. Tanto o runtime quanto o modelo de programação usam o número 4 como a versão principal mais recente, mas isso é uma coincidência.
  • Não é possível usar os modelos de programação v3 e v4 no mesmo aplicativo de funções. Assim que você registra uma função v4 no aplicativo, todas as funções v3 registradas nos arquivos function.json são ignoradas.

Requisitos

A versão 4 do modelo de programação Node.js requer as seguintes versões mínimas:

Incluir o pacote npm

Na v4, o pacote npm @azure/functions contém o código-fonte primário que dá suporte ao modelo de programação do Node.js. Nas versões anteriores, esse código enviado diretamente no Azure e no pacote npm tinha somente os tipos TypeScript. Agora você precisa incluir esse pacote para aplicativos TypeScript e JavaScript. Você pode incluir o pacote para aplicativos v3 existentes, mas ele não é necessário.

Dica

Verifique se o pacote @azure/functions está listado na seção dependencies (não devDependencies) do arquivo package.json. Você pode instalar a v4 usando o seguinte comando:

npm install @azure/functions

Definir o ponto de entrada do aplicativo

Na v4 do modelo de programação, você pode estruturar seu código como desejar. Os únicos arquivos necessários na raiz do aplicativo são host.json e package.json.

Caso contrário, configure a estrutura do arquivo definindo o campo main no arquivo package.json. Você pode definir o campo main como um único arquivo ou como diversos usando um padrão glob. A tabela a seguir mostra valores de exemplo para o campo main:

Exemplo Descrição
src/index.js Registrar funções de um único arquivo raiz.
src/functions/*.js Registrar cada função de seu próprio arquivo.
src/{index.js,functions/*.js} Uma combinação em que você registra cada função de seu próprio arquivo, mas ainda tem um arquivo raiz para código geral no nível do aplicativo.
Exemplo Descrição
dist/src/index.js Registrar funções de um único arquivo raiz.
dist/src/functions/*.js Registrar cada função de seu próprio arquivo.
dist/src/{index.js,functions/*.js} Uma combinação em que você registra cada função de seu próprio arquivo, mas ainda tem um arquivo raiz para código geral no nível do aplicativo.

Dica

Defina um campo main no arquivo package.json.

Alternar a ordem dos argumentos

A entrada do gatilho, em vez do contexto de invocação, agora é o primeiro argumento para o manipulador de funções. O contexto de invocação, agora o segundo argumento, é simplificado na v4 e não é tão necessário quanto a entrada do gatilho. Se não for usá-lo, você poderá deixá-lo desativado.

Dica

Alterne a ordem dos argumentos. Por exemplo, se você não estiver usando o contexto, alterne (context, request) para (request, context) ou apenas (request) ao usar um gatilho HTTP.

Definir sua função no código

Você não precisa mais criar e manter esses arquivos de configuração function.json separados. Agora é possível definir totalmente as funções diretamente nos arquivos TypeScript ou JavaScript. Além disso, muitas propriedades agora têm padrões para que você não precise especificá-las todas as vezes.

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,
});

Dica

Mova a configuração do arquivo function.json para o código. O tipo do gatilho corresponde a um método no objeto app do novo modelo. Por exemplo, ao usar um tipo httpTrigger em function.json, chame app.http() no código para registrar a função. Ao usar timerTrigger, chame app.timer().

Examinar o uso do contexto

Na v4, o objeto context é simplificado para reduzir a duplicação e facilitar a gravação de testes de unidade. Por exemplo, a entrada e a saída primárias foram simplificadas para serem acessadas apenas como o argumento e o valor retornado do manipulador de funções.

Não é mais possível acessar a entrada e a saída primárias no objeto context, mas ainda é possível acessar entradas e saídas secundárias no objeto context. Para obter mais informações sobre entradas e saídas secundárias, confira o guia do desenvolvedor Node.js.

Obter a entrada primária como um argumento

A entrada primária também é chamada de gatilho e é a única entrada ou saída necessária. Você deve ter um (e apenas um) gatilho.

A versão 4 só aceita uma forma de obter a entrada do gatilho, como o primeiro argumento:

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

Dica

Verifique se você não está usando context.req ou context.bindings para obter a entrada.

Definir a saída primária como valor retornado

A versão 4 aceita uma única forma de definir a saída primária por meio do valor retornado:

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

Dica

Sempre retorne a saída no manipulador de funções, em vez de defini-la com o objeto context.

Registro de contexto

Na v4, os métodos de registro foram movidos para o objeto raiz context, conforme mostrado no exemplo a seguir. Para obter mais informações sobre registro, veja o guia do desenvolvedor do Node.js.

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

Criar um contexto de teste

Como a versão 3 não aceita a criação de um contexto de invocação fora do runtime do Azure Functions, a criação de testes de unidade pode ser difícil. A versão 4 permite criar uma instância do contexto de invocação, mas as informações durante os testes não são detalhadas, a menos que você as adicione por conta própria.

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

Examinar o uso de tipos HTTP

Os tipos de solicitação e resposta HTTP agora são um subconjunto do padrão de busca. Eles não são mais exclusivos do Azure Functions.

Os tipos usam o pacote undici no Node.js. Esse pacote segue o padrão de busca e está sendo integrado atualmente ao núcleo do Node.js.

HttpRequest

  • Corpo. Para acessar o corpo, use um método específico do tipo que você deseja receber:

    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();
    
  • Cabeçalho:

    const header = request.headers.get('content-type');
    
  • Parâmetro de consulta:

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

HttpResponse

  • Status:

    return { status: 200 };
    
  • Corpo:

    Use a propriedade body para retornar a maioria dos tipos como um string ou Buffer:

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

    Use a propriedade jsonBody para a maneira mais fácil de retornar uma resposta JSON:

    return { jsonBody: { hello: "world" } };
    
  • Cabeçalho. Você pode definir o cabeçalho de duas maneiras, e elas estão relacionadas ao uso da classe HttpResponse ou da interface HttpResponseInit:

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

Dica

Atualize qualquer lógica usando os tipos de solicitação ou resposta HTTP para corresponder aos novos métodos.

Dica

Atualize qualquer lógica usando os tipos de solicitação ou resposta HTTP para corresponder aos novos métodos. Você deve obter erros de compilação do TypeScript para ajudar a identificar se está usando métodos antigos.

Solucionar problemas

Confira o guia de solução de problemas do Node.js.