Criar e implantar um aplicativo Web estático no Azure

Neste tutorial, crie e implante localmente um aplicativo cliente React/TypeScript em um Aplicativo Web Estático do Azure com uma ação do GitHub. O aplicativo React permite analisar uma imagem com o Cognitive Services Computer Vision.

Criar ou usar uma assinatura existente do Azure

Você precisará de uma conta de usuário do Azure com uma assinatura ativa. Crie um gratuitamente.

Pré-requisitos

  • Node.js e npm - instalados na sua máquina local.
  • Visual Studio Code - instalado em sua máquina local.
    • Aplicativos Web Estáticos do Azure - usados para implantar o aplicativo React no aplicativo Web Estático do Azure.
  • Git - usado para enviar por push para o GitHub - que ativa a ação do GitHub.
  • Conta GitHub - para bifurcar e empurrar para um repositório
  • Utilize o Azure Cloud Shell com o ambiente do Bash.
  • Uma função de Contribuidor dos Serviços Cognitivos tem de estar atribuída à conta do Azure para poder aceitar os termos da IA responsável e criar um recurso. Para atribuir essa função à sua conta, siga as etapas na documentação Atribuir funções ou entre em contato com o administrador.

O que é um aplicativo Web estático do Azure

Ao criar aplicativos Web estáticos, você tem várias opções no Azure, com base no grau de funcionalidade e controle em que está interessado. Este tutorial se concentra no serviço mais fácil com muitas das escolhas feitas para você, para que você possa se concentrar em seu código front-end e não no ambiente de hospedagem.

O React (create-react-app) fornece a seguinte funcionalidade:

  • Exibir mensagem se a chave e o ponto de extremidade do Azure para Visão Computacional dos Serviços Cognitivos não forem encontrados
  • Permite analisar uma imagem com Visão Computacional de Serviços Cognitivos
    • Insira um URL de imagem pública ou analise a imagem da coleção
    • Quando a análise estiver concluída
      • Imagem a apresentar
      • Exibir resultados JSON de Visão por Computador

Partial browser screenshot of React Cognitive Service Computer Vision sample results.

Para implantar o aplicativo Web estático, use uma ação do GitHub, que começa quando ocorre um push para uma ramificação específica:

  • Insere segredos do GitHub para chave e ponto de extremidade do Computer Vision na compilação
  • Cria o cliente React (create-react-app)
  • Move os arquivos resultantes para o recurso do aplicativo Web estático do Azure

1. Forquilhar o repositório de amostras

Fork o repositório, em vez de apenas cloná-lo para o seu computador local, a fim de ter um repositório GitHub próprio para enviar as alterações.

  1. Abra uma janela ou guia separada do navegador e faça login no GitHub.

  2. Navegue até o repositório de exemplo do GitHub.

    https://github.com/Azure-Samples/js-e2e-client-cognitive-services
    
  3. Na seção superior direita da página, selecione Forquilha.

  4. Selecione Código e, em seguida, copie o URL de localização para a bifurcação.

    Partial screenshot of GitHub website, select **Code** then copy the location for your fork.

2. Criar um ambiente de desenvolvimento local

  1. Em uma janela de terminal ou bash, clone sua bifurcação para o computador local. Substitua YOUR-ACCOUNT-NAME pelo nome da sua conta do GitHub.

    git clone https://github.com/YOUR-ACCOUNT-NAME/js-e2e-client-cognitive-services
    
  2. Mude para o novo diretório e instale as dependências.

    cd js-e2e-client-cognitive-services && npm install
    

    A etapa de instalação instala as dependências necessárias, incluindo @azure/cognitiveservices-computervision.

3. Execute o exemplo local

  1. Execute o exemplo.

    npm start
    

    Partial browser screenshot of React Cognitive Service Computer Vision sample for image analysis before key and endpoint set.

  2. Pare a aplicação. Feche a janela do terminal ou use control+c no terminal.

4. Crie o seu grupo de recursos

Em um terminal ou shell bash, insira o comando CLI do Azure para criar um grupo de recursos do Azure, com o nome rg-demo:

az group create \
    --location eastus \
    --name rg-demo \
    --subscription YOUR-SUBSCRIPTION-NAME-OR-ID

5. Crie um recurso de Visão por Computador

Criar um grupo de recursos permite que você encontre facilmente os recursos e os exclua quando terminar. Esse tipo de recurso requer que você concorde com o contrato de Uso Responsável. Use a lista a seguir para saber como você pode criar rapidamente o recurso correto:

6. Crie o seu primeiro recurso de Visão por Computador

Se este for o seu primeiro serviço de IA, você deve criar o serviço através do portal e concordar com o contrato de Uso Responsável, como parte da criação desse recurso. Se este não for o seu primeiro recurso que requer o contrato de Uso Responsável, você pode criar o recurso com a CLI do Azure, encontrada na próxima seção.

Use a tabela a seguir para ajudar a criar o recurso no portal do Azure.

Definição valor
Grupo de recursos RG-Demonstração
Nome demonstração-ComputerVision
Sku S1
Localização eastus

7. Crie um recurso adicional de Visão por Computador

Execute o seguinte comando para criar um recurso de Visão Computacional:

az cognitiveservices account create \
    --name demo-ComputerVision \
    --resource-group rg-demo \
    --kind ComputerVision \
    --sku S1 \
    --location eastus \
    --yes

8. Obtenha o ponto final e as chaves do recurso de Visão Computacional

  1. Nos resultados, localize e copie o properties.endpointarquivo . Você vai precisar disso mais tarde.

    ...
    "properties":{
        ...
        "endpoint": "https://eastus.api.cognitive.microsoft.com/",
        ...
    }
    ...
    
  2. Execute o seguinte comando para obter suas chaves.

    az cognitiveservices account keys list \
    --name demo-ComputerVision \
    --resource-group rg-demo
    
  3. Copie uma das chaves, você precisará disso mais tarde.

    {
      "key1": "8eb7f878bdce4e96b26c89b2b8d05319",
      "key2": "c2067cea18254bdda71c8ba6428c1e1a"
    }
    

9. Adicione variáveis de ambiente ao seu ambiente local

Para usar seu recurso, o código local precisa ter a chave e o ponto de extremidade disponíveis. Esta base de código armazena as variáveis de ambiente:

  • REACT_APP_AZURE_COMPUTER_VISION_KEY
  • REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT
  1. Execute o seguinte comando para adicionar essas variáveis ao seu ambiente.

    export REACT_APP_AZURE_COMPUTER_VISION_KEY="REPLACE-WITH-YOUR-KEY"
    export REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT="REPLACE-WITH-YOUR-ENDPOINT"
    

10. Adicione variáveis de ambiente ao seu ambiente remoto

Ao usar aplicativos Web estáticos do Azure, variáveis de ambiente, como segredos, precisam ser passadas da ação GitHub para o aplicativo Web estático. A ação do GitHub cria o aplicativo, incluindo a chave de Visão do Computador e o ponto de extremidade passados dos segredos do GitHub para esse repositório e, em seguida, envia o código com as variáveis de ambiente para o aplicativo Web estático.

  1. Em um navegador da Web, no repositório GitHub, selecione Configurações, Segredos e Novo segredo do repositório.

    Partial browser screenshot of GitHub repository, creating new repository secret.

  2. Insira o mesmo nome e valor para o ponto de extremidade usado na seção anterior. Em seguida, crie outro segredo com o mesmo nome e valor para a chave usada na seção anterior.

    Enter the same name and value for the endpoint. Then create another secret with the same name and value for the key.

11. Execute o aplicativo react local com o recurso ComputerVision

  1. Inicie o aplicativo novamente, na linha de comando:

    npm start
    

    Partial browser screenshot of React Cognitive Service Computer Vision sample ready for URL or press enter.

  2. Deixe o campo de texto vazio para selecionar uma imagem do catálogo padrão e selecione o botão Analisar .

    Partial browser screenshot of React Cognitive Service Computer Vision sample results.

    A imagem é selecionada aleatoriamente a partir de um catálogo de imagens definido em ./src/DefaultImages.js.

  3. Continue a selecionar o botão Analisar para ver as outras imagens e resultados.

12. Empurre a filial local para o GitHub

No terminal do Visual Studio Code, envie a ramificação main local para o repositório remoto.

git push origin main

Você não precisou confirmar nenhuma alteração porque nenhuma alteração foi feita ainda.

13. Criar um recurso de aplicativo Web estático

  1. Selecione o ícone do Azure e, em seguida, clique com o botão direito do rato no serviço Static Web Apps e, em seguida, selecione Create Static Web App (Advanced).

    Visual Studio Code screenshot with Visual Studio extension

  2. Se uma janela pop-up perguntar se você deseja continuar na main ramificação, selecione Continuar.

  3. Insira as seguintes informações nos campos subsequentes, apresentados um de cada vez.

    Nome do campo valor
    Selecione um grupo de recursos para novos recursos. Selecione o grupo de recursos que você criou para o recurso ComputerVision, demo-ComputerVision.
    Insira um nome para o novo aplicativo Web estático. Demo-ComputerVisionAnalyzer
    Selecione a opção de preço Selecione livre.
    Selecione o local do código do seu aplicativo. Selecione o mesmo local selecionado quando criou o grupo de recursos, eastus.
    Escolha a predefinição de compilação para configurar a estrutura padrão do projeto. React
    Escolha o local do código do seu aplicativo. /
    Insira o local do seu código do Azure Functions. Pegue o valor padrão.
    Insira o caminho da saída da compilação em relação à localização do aplicativo. build

14. Atualize a ação do GitHub com variáveis de ambiente secretas

A chave e o ponto de extremidade do Computer Vision estão na coleção de segredos do repositório, mas ainda não estão na ação do GitHub. Esta etapa adiciona a chave e o ponto de extremidade à ação.

  1. Puxe para baixo as alterações feitas na criação do recurso do Azure para obter o arquivo de ação do GitHub.

    git pull origin main
    
  2. No editor de código do Visual Studio, edite o arquivo de ação do GitHub encontrado em ./.github/workflows/ para adicionar os segredos.

    name: Azure Static Web Apps CI/CD
    
    on:
      push:
        branches:
          - from-local
      pull_request:
        types: [opened, synchronize, reopened, closed]
        branches:
          - from-local
    
    jobs:
      build_and_deploy_job:
        if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
        runs-on: ubuntu-latest
        name: Build and Deploy Job
        steps:
          - uses: actions/checkout@v2
            with:
              submodules: true
          - name: Build And Deploy
            id: builddeploy
            uses: Azure/static-web-apps-deploy@v0.0.1-preview
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_RANDOM_NAME_HERE }}
              repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
              action: "upload"
              ###### Repository/Build Configurations - These values can be configured to match you app requirements. ######
              # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
              app_location: "/" # App source code path
              api_location: "api" # Api source code path - optional
              output_location: "build" # Built app content directory - optional
              ###### End of Repository/Build Configurations ######
            env:
              REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT: ${{secrets.REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT}}
              REACT_APP_AZURE_COMPUTER_VISION_KEY:  ${{secrets.REACT_APP_AZURE_COMPUTER_VISION_KEY}}
    
      close_pull_request_job:
        if: github.event_name == 'pull_request' && github.event.action == 'closed'
        runs-on: ubuntu-latest
        name: Close Pull Request Job
        steps:
          - name: Close Pull Request
            id: closepullrequest
            uses: Azure/static-web-apps-deploy@v0.0.1-preview
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_RANDOM_NAME_HERE }}
              action: "close"
    
  3. Adicione e confirme a alteração na ramificação local main .

    git add . && git commit -m "add secrets to action"
    
  4. Envie a alteração por push para o repositório remoto, iniciando uma nova ação de compilação e implantação em seu aplicativo Web Estático do Azure.

    git push origin main
    

15. Veja o processo de compilação da Ação do GitHub

  1. Em um navegador da Web, abra o repositório GitHub para este tutorial e selecione Ações.

  2. Selecione a compilação superior na lista e, em seguida, selecione Build and Deploy Job no menu do lado esquerdo para assistir ao processo de compilação. Aguarde até que a compilação e a implantação sejam concluídas com êxito.

     Select the top build in the list, then select `Build and Deploy Job` on the left-side menu to watch the build process. Wait until the build successfully finishes.

16. Exibir site estático remoto do Azure no navegador

  1. No Visual Studio Code, selecione o ícone do Azure no menu mais à direita, selecione seu aplicativo Web estático, clique com o botão direito do mouse em Procurar site e selecione Abrir para exibir o site estático público.

Select `Browse site`, then select `Open` to view the public static web site.

Você também pode encontrar o URL do site em:

  • o portal do Azure para o seu recurso, na página Visão geral .
  • a saída build-and-deploy da ação GitHub tem a URL do site no final do script

17. Limpar recursos para aplicações Web estáticas

Depois de concluir este tutorial, você precisa remover o grupo de recursos, que inclui o recurso Visão Computacional e o aplicativo Web estático, para garantir que você não seja cobrado por mais uso.

No VS Code, selecione o explorador do Azure, clique com o botão direito do rato no seu grupo de recursos listado na subscrição e selecione Eliminar.

Partial screen shot of VS Code, selecting resource group from list of resource groups, then right-clicking to select `Delete`.

Código: Adicionar Visão Computacional ao aplicativo React local

Use npm para adicionar Visão Computacional ao arquivo package.json.

npm install @azure/cognitiveservices-computervision 

Código: Adicionar código de Visão Computacional como módulo separado

O código Computer Vision está contido em um arquivo separado chamado ./src/azure-cognitiveservices-computervision.js. A principal função do módulo é destacada.

// ./src/azure-cognitiveservices-computervision.js

// Azure SDK client libraries
import { ComputerVisionClient } from '@azure/cognitiveservices-computervision';
import { ApiKeyCredentials } from '@azure/ms-rest-js';

// List of sample images to use in demo
import RandomImageUrl from './DefaultImages';

// Authentication requirements
const key = process.env.REACT_APP_AZURE_COMPUTER_VISION_KEY;
const endpoint = process.env.REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT;

console.log(`key = ${key}`)
console.log(`endpoint = ${endpoint}`)

// Cognitive service features
const visualFeatures = [
    "ImageType",
    "Faces",
    "Adult",
    "Categories",
    "Color",
    "Tags",
    "Description",
    "Objects",
    "Brands"
];

export const isConfigured = () => {
    const result = (key && endpoint && (key.length > 0) && (endpoint.length > 0)) ? true : false;
    console.log(`key = ${key}`)
    console.log(`endpoint = ${endpoint}`)
    console.log(`ComputerVision isConfigured = ${result}`)
    return result;
}

// Computer Vision detected Printed Text
const includesText = async (tags) => {
    return tags.filter((el) => {
        return el.name.toLowerCase() === "text";
    });
}
// Computer Vision detected Handwriting
const includesHandwriting = async (tags) => {
    return tags.filter((el) => {
        return el.name.toLowerCase() === "handwriting";
    });
}
// Wait for text detection to succeed
const wait = (timeout) => {
    return new Promise(resolve => {
        setTimeout(resolve, timeout);
    });
}

// Analyze Image from URL
export const computerVision = async (url) => {

    // authenticate to Azure service
    const computerVisionClient = new ComputerVisionClient(
        new ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': key } }), endpoint);

    // get image URL - entered in form or random from Default Images
    const urlToAnalyze = url || RandomImageUrl();
    
    // analyze image
    const analysis = await computerVisionClient.analyzeImage(urlToAnalyze, { visualFeatures });

    // text detected - what does it say and where is it
    if (includesText(analysis.tags) || includesHandwriting(analysis.tags)) {
        analysis.text = await readTextFromURL(computerVisionClient, urlToAnalyze);
    }

    // all information about image
    return { "URL": urlToAnalyze, ...analysis};
}
// analyze text in image
const readTextFromURL = async (client, url) => {
    
    let result = await client.read(url);
    let operationID = result.operationLocation.split('/').slice(-1)[0];

    // Wait for read recognition to complete
    // result.status is initially undefined, since it's the result of read
    const start = Date.now();
    console.log(`${start} -${result?.status} `);
    
    while (result.status !== "succeeded") {
        await wait(500);
        console.log(`${Date.now() - start} -${result?.status} `);
        result = await client.getReadResult(operationID);
    }
    
    // Return the first page of result. 
    // Replace[0] with the desired page if this is a multi-page file such as .pdf or.tiff.
    return result.analyzeResult; 
}

Código: Adicionar catálogo de imagens como módulo separado

O aplicativo seleciona uma imagem aleatória de um catálogo se o usuário não inserir uma URL de imagem. A função de seleção aleatória é realçada

// ./src/DefaultImages.js

const describeURL = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/celebrities.jpg';
const categoryURLImage = 'https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png';
const tagsURL = 'https://moderatorsampleimages.blob.core.windows.net/samples/sample16.png';
const objectURL = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-node-sdk-samples/master/Data/image.jpg';
const brandURLImage = 'https://docs.microsoft.com/en-us/azure/cognitive-services/computer-vision/images/red-shirt-logo.jpg';
const facesImageURL = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/faces.jpg';
const printedTextSampleURL = 'https://moderatorsampleimages.blob.core.windows.net/samples/sample2.jpg';
const multiLingualTextURL = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/MultiLingual.png';
const adultURLImage = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/celebrities.jpg';
const colorURLImage = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/celebrities.jpg';
// don't use with picture analysis
// eslint-disable-next-line
const mixedMultiPagePDFURL = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/MultiPageHandwrittenForm.pdf';
const domainURLImage = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/landmark.jpg';
const typeURLImage = 'https://raw.githubusercontent.com/Azure-Samples/cognitive-services-python-sdk-samples/master/samples/vision/images/make_things_happen.jpg';

const DefaultImages = [
    describeURL,
    categoryURLImage,
    tagsURL,
    objectURL,
    brandURLImage,
    facesImageURL,
    adultURLImage,
    colorURLImage,
    domainURLImage,
    typeURLImage,
    printedTextSampleURL,
    multiLingualTextURL,
    //mixedMultiPagePDFURL
];

const RandomImageUrl = () => {
    return DefaultImages[Math.floor(Math.random() * Math.floor(DefaultImages.length))];
}

export default RandomImageUrl;

Código: Adicionar módulo de Visão Computacional personalizado ao aplicativo React

Adicione métodos ao React app.js. A análise da imagem e a exibição dos resultados são destacadas.

// ./src/App.js

import React, { useState } from 'react';
import './App.css';
import { computerVision, isConfigured as ComputerVisionIsConfigured } from './azure-cognitiveservices-computervision';

function App() {

  const [fileSelected, setFileSelected] = useState(null);
  const [analysis, setAnalysis] = useState(null);
  const [processing, setProcessing] = useState(false);
  
  const handleChange = (e) => {
    setFileSelected(e.target.value)
  }
  const onFileUrlEntered = (e) => {

    // hold UI
    setProcessing(true);
    setAnalysis(null);

    computerVision(fileSelected || null).then((item) => {
      // reset state/form
      setAnalysis(item);
      setFileSelected("");
      setProcessing(false);
    });

  };

  // Display JSON data in readable format
  const PrettyPrintJson = (data) => {
    return (<div><pre>{JSON.stringify(data, null, 2)}</pre></div>);
  }

  const DisplayResults = () => {
    return (
      <div>
        <h2>Computer Vision Analysis</h2>
        <div><img src={analysis.URL} height="200" border="1" alt={(analysis.description && analysis.description.captions && analysis.description.captions[0].text ? analysis.description.captions[0].text : "can't find caption")} /></div>
        {PrettyPrintJson(analysis)}
      </div>
    )
  };
  
  const Analyze = () => {
    return (
    <div>
      <h1>Analyze image</h1>
      {!processing &&
        <div>
          <div>
            <label>URL</label>
            <input type="text" placeholder="Enter URL or leave empty for random image from collection" size="50" onChange={handleChange}></input>
          </div>
          <button onClick={onFileUrlEntered}>Analyze</button>
        </div>
      }
      {processing && <div>Processing</div>}
      <hr />
      {analysis && DisplayResults()}
      </div>
    )
  }
  
  const CantAnalyze = () => {
    return (
      <div>Key and/or endpoint not configured in ./azure-cognitiveservices-computervision.js</div>
    )
  }
  
  function Render() {
    const ready = ComputerVisionIsConfigured();
    if (ready) {
      return <Analyze />;
    }
    return <CantAnalyze />;
  }

  return (
    <div>
      {Render()}
    </div>
    
  );
}

export default App;

Próximos passos