Compilare e distribuire un'app Web statica in Azure

In questa esercitazione, si compila e si distribuisce localmente un'applicazione client React/TypeScript in un'app Web statica di Azure con un'azione GitHub. L'app React consente di analizzare un'immagine con Visione artificiale di Servizi cognitivi.

Creare o usare una sottoscrizione di Azure esistente

È necessario un account utente di Azure con una sottoscrizione attiva. Crearne una gratuitamente.

Prerequisiti

  • Node.js e npm: installati nel computer locale.
  • Visual Studio Code: installato nel computer locale.
    • App Web statiche di Azure: usato per distribuire l'app React nell'app Web statica di Azure.
  • Git: usato per eseguire il push in GitHub, che attiva l'azione GitHub.
  • Account GitHub: per creare una copia tramite fork ed eseguire il push in un repository
  • Usare Azure Cloud Shell tramite l'ambiente bash.
  • L'account Azure deve avere un ruolo di Collaboratore servizi cognitivi assegnato per poter accettare le condizioni di intelligenza artificiale responsabili e creare una risorsa. Per assegnare questo ruolo all'account, seguire la procedura descritta nella documentazione Assegnare ruoli oppure contattare l'amministratore.

Che cos'è un'app Web statica di Azure

Quando si compilano app Web statiche, sono disponibili diverse opzioni in Azure, in base al grado di funzionalità e al controllo a cui si è interessati. Questa esercitazione è incentrata sul servizio più semplice con molte delle scelte effettuate per l'utente, per potersi concentrare sul codice front-end e non sull'ambiente host.

Il client React (create-react-app) fornisce le funzionalità seguenti:

  • Visualizza un messaggio se la chiave e l'endpoint di Azure per Visione artificiale di Servizi cognitivi non sono stati trovati
  • Consente di analizzare un'immagine con Servizi cognitivi Visione artificiale
    • Immettere un URL di immagine pubblico o analizzare l'immagine dalla raccolta
    • Al termine dell'analisi
      • Immagine visualizzata
      • Visualizzare i risultati JSON di Visione artificiale

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

Per distribuire l'app Web statica, usare un'azione GitHub, che inizia quando si verifica un push in un ramo specifico:

  • Inserisce i segreti GitHub per la chiave e l'endpoint di Visione artificiale nella build
  • Compila il client React (create-react-app)
  • Sposta i file risultanti nella risorsa app Web statica di Azure

1. Creare una copia tramite fork del repository di esempio

Creare una copia tramite fork del repository, invece di limitarsi a clonarlo nel computer locale, per poter avere un proprio repository GitHub in cui eseguire il push delle modifiche.

  1. Aprire una finestra o una scheda del browser a parte per accedere a GitHub.

  2. Passare al repository di esempio GitHub.

    https://github.com/Azure-Samples/js-e2e-client-cognitive-services
    
  3. In alto a destra nella pagina selezionare Fork.

  4. Selezionare Code quindi copiare l'URL del percorso per il fork.

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

2. Creare un ambiente di sviluppo locale

  1. In una finestra terminale o bash clonare il fork nel computer locale. Sostituire YOUR-ACCOUNT-NAME con il nome dell'account GitHub.

    git clone https://github.com/YOUR-ACCOUNT-NAME/js-e2e-client-cognitive-services
    
  2. Passare alla nuova directory e installare le dipendenze.

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

    Il passaggio di installazione installa le dipendenze necessarie, tra cui @azure/cognitiveservices-computervision.

3. Eseguire l'esempio locale

  1. Eseguire l'esempio.

    npm start
    

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

  2. Arrestare l'app. Chiudere la finestra del terminale o usare control+c nel terminale.

4. Creare il gruppo di risorse

In un terminale o in una shell Bash, immettere il comando dell'interfaccia della riga di comando di Azure per creare un gruppo di risorse di Azure con il nome rg-demo:

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

5. Creare una risorsa Visione artificiale

La creazione di un gruppo di risorse consente di trovare facilmente le risorse ed eliminarle al termine dell'operazione. Questo tipo di risorsa richiede che l'utente accetti il contratto di utilizzo responsabile. Usare l'elenco seguente per sapere come creare rapidamente la risorsa corretta:

6. Creare la prima risorsa Visione artificiale

Se si tratta del primo servizio di intelligenza artificiale, è necessario creare il servizio tramite il portale e accettare il contratto Di utilizzo responsabile, come parte della creazione di tale risorsa. Se questa non è la prima risorsa che richiede il contratto di utilizzo responsabile, è possibile creare la risorsa con l'interfaccia della riga di comando di Azure, disponibile nella sezione successiva.

Usare la tabella seguente per creare la risorsa all'interno del portale di Azure.

Impostazione Valore
Gruppo di risorse rg-demo
Nome demo-ComputerVision
Sku S1
Ufficio eastus

7. Creare una risorsa di Visione artificiale aggiuntiva

Eseguire il comando seguente per creare una risorsa di Visione artificiale:

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

8. Ottenere l'endpoint e le chiavi della risorsa Visione artificiale

  1. Nei risultati trovare e copiare il valore della properties.endpoint. che sarà necessario più avanti.

    ...
    "properties":{
        ...
        "endpoint": "https://eastus.api.cognitive.microsoft.com/",
        ...
    }
    ...
    
  2. Eseguire il comando seguente per ottenere le chiavi.

    az cognitiveservices account keys list \
    --name demo-ComputerVision \
    --resource-group rg-demo
    
  3. Copiare una delle chiavi: sarà necessaria in un secondo momento.

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

9. Aggiungere variabili di ambiente all'ambiente locale

Per usare la risorsa, la chiave e l'endpoint devono essere disponibili nel codice locale. Questa codebase li archivia nelle variabili di ambiente:

  • REACT_APP_AZURE_COMPUTER_VISION_KEY
  • REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT
  1. Eseguire il comando riportato di seguito per aggiungere queste variabili all'ambiente.

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

10. Aggiungere variabili di ambiente all'ambiente remoto

Quando si usano app Web statiche di Azure, le variabili di ambiente, come i segreti, devono essere passate dall'azione GitHub all'app Web statica. L'azione GitHub compila l'app, inclusi la chiave e l'endpoint di Visione artificiale passati dai segreti di GitHub per tale repository, quindi esegue il push del codice con le variabili di ambiente nell'app Web statica.

  1. Nel repository GitHub in un Web browser, selezionare Settings (Impostazioni), quindi Secrets (Segreti) e infine New repository secret (Nuovo segreto del repository).

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

  2. Immettere lo stesso nome e valore per l'endpoint usato nella sezione precedente. Quindi, creare un altro segreto con lo stesso nome e il medesimo valore della chiave usati nella sezione precedente.

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

11. Eseguire l'app React locale con la risorsa ComputerVision

  1. Avviare di nuovo l'app alla riga di comando:

    npm start
    

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

  2. Lasciare vuoto il campo di testo per selezionare un'immagine del catalogo predefinito, quindi selezionare il pulsante Analizza.

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

    L'immagine viene selezionata in modo casuale da un catalogo di immagini definite in ./src/DefaultImages.js.

  3. Continuare a selezionare il pulsante Analyze per visualizzare le altre immagini e i risultati.

12. Eseguire il push del ramo locale in GitHub

Nel terminale di Visual Studio Code eseguire il push del ramo locale main nel repository remoto.

git push origin main

Non è stato necessario eseguire il commit di alcuna modifica perché non sono state ancora apportate modifiche.

13. Creare una risorsa app Web statica

  1. Selezionare l'icona di Azure, quindi fare clic con il pulsante destro del mouse sul servizio App Web statiche, quindi scegliere Crea app Web statica (avanzate).

    Visual Studio Code screenshot with Visual Studio extension

  2. Se una finestra popup chiede se si vuole continuare nel main ramo, selezionare Continua.

  3. Immettere le informazioni seguenti nei campi successivi, presentati uno alla volta.

    Nome del campo value
    Selezionare un gruppo di risorse per le nuove risorse. Selezionare il gruppo di risorse creato per la risorsa ComputerVision, demo-ComputerVision.
    Enter a name for the new static web app. Demo-ComputerVisionAnalyzer
    Selezionare l'opzione dei prezzi Selezionare gratuito.
    Selezionare il percorso del codice dell'applicazione. Selezionare la stessa località selezionata al momento della creazione del gruppo di risorse. eastus
    Scegliere il set di impostazioni di compilazione per configurare la struttura predefinita del progetto. React
    Scegliere il percorso del codice dell'applicazione. /
    Immettere il percorso del codice Funzioni di Azure. Accettare il valore predefinito.
    Immettere il percorso dell'output di compilazione relativo alla posizione dell'app. build

14. Aggiornare l'azione GitHub con le variabili di ambiente segrete

La chiave e l'endpoint di Visione artificiale si trovano nella raccolta di segreti del repository, ma non sono ancora presenti nell'azione GitHub. Questo passaggio aggiunge la chiave e l'endpoint all'azione.

  1. Rimuovere le modifiche apportate dalla creazione della risorsa di Azure per ottenere il file di azione GitHub.

    git pull origin main
    
  2. Nell'editor di Visual Studio Code modificare il file di azione GitHub in ./.github/workflows/ per aggiungere i segreti.

    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. Aggiungere ed eseguire il commit della modifica nel ramo main locale.

    git add . && git commit -m "add secrets to action"
    
  4. Eseguire il push della modifica nel repository remoto, avviando una nuova azione di compilazione e distribuzione nell'app Web statica di Azure.

    git push origin main
    

15. Visualizzare il processo di compilazione di GitHub Action

  1. In un Web browser aprire il repository GitHub per questa esercitazione e selezionare Actions (Azioni).

  2. Selezionare la build principale nell'elenco, quindi selezionare Build and Deploy Job (Compila e distribuisci processo) nel menu a sinistra per controllare il processo di compilazione. Attendere fino a quando non viene completata la compilazione e distribuzione.

     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. Visualizzare il sito Web statico di Azure remoto nel browser

  1. In Visual Studio Code selezionare l'icona Azure nel menu a destra, quindi selezionare l'app Web statica, fare clic con il pulsante destro del mouse su Esplorazione del sito, infine selezionare Apri per visualizzare il sito Web statico pubblico.

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

È anche possibile trovare l'URL per il sito dove segue:

  • il portale di Azure per la propria risorsa, nella pagina Panoramica.
  • l'output di compilazione e distribuzione dell'azione GitHub contiene l'URL del sito alla fine dello script

17. Pulire le risorse per l'app Web statica

Al termine di questa esercitazione, è necessario rimuovere il gruppo di risorse, incluse la risorsa Visione artificiale e l'app Web statica, per evitare di ricevere addebiti per ulteriori utilizzi.

In VS Code selezionare Esplora risorse di Azure, quindi fare clic con il pulsante destro del mouse sul gruppo di risorse elencato nella sottoscrizione e selezionare Elimina.

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

Codice: aggiungere Visione artificiale all'app React locale

Usare npm per aggiungere Visione artificiale al file package.json.

npm install @azure/cognitiveservices-computervision 

Codice: aggiungere codice Visione artificiale come modulo separato

Il codice di Visione artificiale è contenuto in un file separato denominato ./src/azure-cognitiveservices-computervision.js. La funzione principale del modulo è evidenziata.

// ./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; 
}

Codice: Aggiungere il catalogo di immagini come modulo separato

L'app seleziona un'immagine casuale da un catalogo se l'utente non immette un URL di immagine. La funzione di selezione casuale è evidenziata

// ./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;

Codice: Aggiungere un modulo di Visione artificiale personalizzato all'app React

Aggiungere metodi al file app.js dell'app React. L'analisi delle immagini e la visualizzazione dei risultati sono evidenziate.

// ./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;

Passaggi successivi