Créer et déployer une application web statique sur Azure

Dans ce tutoriel, créez et déployez localement une application cliente React/TypeScript sur une application web statique Azure avec une action GitHub. L’application React vous permet d’analyser une image avec Vision par ordinateur de Cognitive Services.

Créer ou utiliser un abonnement Azure existant

Vous devez disposer d’un compte d’utilisateur Azure avec un abonnement actif. Créez-en un gratuitement.

Prérequis

  • Node.js et npm installés sur votre machine locale.
  • Visual Studio Code installé sur votre machine locale.
    • Azure Static Web Apps : utilisé pour déployer l’application React sur une application web statique Azure.
  • Git : utilisé pour l’envoi (push) vers GitHub, qui active l’action GitHub.
  • Compte GitHub pour dupliquer (fork) et envoyer dans un dépôt
  • Utilisez Azure Cloud Shell à l’aide de l’environnement Bash.
  • Votre compte Azure doit disposer d’un rôle Contributeur Cognitive Services attribué pour vous permettre d’accepter les termes de l’IA responsable et de créer une ressource. Pour que ce rôle soit attribué à votre compte, suivez les étapes de la documentation Attribuer des rôles ou contactez votre administrateur.

Qu’est-ce qu’une application web statique Azure ?

Lors de la création d’applications web statiques, vous disposez de plusieurs options sur Azure, en fonction du degré de fonctionnalité et de contrôle qui vous intéressent. Ce tutoriel est consacré au service le plus facile où un grand nombre de choix sont faits pour vous, ce qui vous permet de vous concentrer sur le code de votre front-end et non pas sur l’environnement d’hébergement.

L’application React (create-react-app) offre les fonctionnalités suivantes :

  • Afficher un message si la clé et le point de terminaison Azure pour Vision par ordinateur de Cognitive Services sont introuvables
  • Vous permet d’analyser une image avec Cognitive Services Vision par ordinateur
    • Entrer une URL d’image publique ou analyser une image de la collection
    • Une fois l’analyse terminée
      • Afficher l’image
      • Afficher les résultats JSON de Vision par ordinateur

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

Pour déployer l’application web statique, utilisez une action GitHub, qui commence lorsqu’une transmission (push) vers une branche spécifique se produit :

  • Insère des secrets GitHub pour la clé et le point de terminaison de Vision par ordinateur dans la build
  • Génère le client React (create-react-app)
  • Déplace les fichiers résultants vers votre ressource d’application web statique Azure

1. Fork the sample repo

Dupliquez le dépôt au lieu de simplement le cloner sur votre ordinateur local, afin de disposer de votre propre dépôt GitHub pour y envoyer des modifications.

  1. Ouvrez une fenêtre ou un onglet de navigateur distinct, puis connectez-vous à GitHub.

  2. Accédez à l’exemple de référentiel GitHub.

    https://github.com/Azure-Samples/js-e2e-client-cognitive-services
    
  3. Dans la section supérieure droite de la page, sélectionnez Fork (Dupliquer).

  4. Sélectionnez Code, puis copiez l’URL de l’emplacement pour votre duplication.

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

2. Créer un environnement de développement local

  1. Dans un terminal ou une fenêtre bash, clonez votre duplication sur votre ordinateur local. Remplacez YOUR-ACCOUNT-NAME par le nom de votre compte GitHub.

    git clone https://github.com/YOUR-ACCOUNT-NAME/js-e2e-client-cognitive-services
    
  2. Accédez au nouveau répertoire et installez les dépendances.

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

    L’étape d’installation installe les dépendances requises, notamment @azure/cognitiveservices-computervision.

3. Exécuter l’exemple local

  1. Exécutez l’exemple.

    npm start
    

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

  2. Arrêtez l’application. Fermez la fenêtre de terminal ou utilisez control+c dans le terminal.

4. Créer votre groupe de ressources

Dans un terminal ou un shell Bash, entrez la commande Azure CLI pour créer un groupe de ressources Azure avec le nom rg-demo :

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

5. Créer une ressource Vision par ordinateur

La création d’un groupe de ressources vous permet de trouver facilement les ressources et de les supprimer quand vous avez terminé. Ce type de ressource vous demande d’accepter l’accord d’utilisation responsable. Utilisez la liste suivante pour savoir comment créer rapidement la bonne ressource :

6. Créez votre première ressource Vision par ordinateur

S’il s’agit de votre premier service IA, vous devez créer le service via le portail et accepter l’accord d’utilisation responsable dans le cadre de la création de cette ressource. S’il ne s’agit pas de votre première ressource exigeant l’accord d’utilisation responsable, vous pouvez créer la ressource avec Azure CLI, comme indiqué dans la section suivante.

Utilisez le tableau suivant pour vous aider à créer la ressource dans le portail Azure.

Paramètre Valeur
Groupe de ressources rg-demo
Nom demo-ComputerVision
Sku S1
Emplacement eastus

7. Créer une ressource Vision par ordinateur supplémentaire

Exécutez la commande suivante pour créer un groupe de ressources Vision par ordinateur :

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

8. Obtenir Vision par ordinateur point de terminaison et clés de ressource

  1. Dans les résultats, recherchez et copiez l’élément properties.endpoint. Vous en aurez besoin ultérieurement.

    ...
    "properties":{
        ...
        "endpoint": "https://eastus.api.cognitive.microsoft.com/",
        ...
    }
    ...
    
  2. Exécutez la commande suivante pour obtenir vos clés.

    az cognitiveservices account keys list \
    --name demo-ComputerVision \
    --resource-group rg-demo
    
  3. Copiez une des clés, car vous en aurez besoin plus tard.

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

9. Ajouter des variables d’environnement à votre environnement local

Pour utiliser votre ressource, la clé et le point de terminaison doivent être disponibles dans le code local. Cette base de code stocke celles-ci dans des variables d’environnement :

  • REACT_APP_AZURE_COMPUTER_VISION_KEY
  • REACT_APP_AZURE_COMPUTER_VISION_ENDPOINT
  1. Exécutez la commande suivante pour ajouter ces variables à votre environnement.

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

10. Ajouter des variables d’environnement à votre environnement distant

Quand vous utilisez des applications web statiques Azure, les variables d’environnement, comme les secrets, doivent être passées de l’action GitHub à l’application web statique. L’action GitHub génère l’application, y compris la clé et le point de terminaison de Vision par ordinateur passés depuis les secrets GitHub pour ce dépôt, puis envoie le code avec les variables d’environnement à l’application web statique.

  1. Dans un navigateur web, dans votre dépôt GitHub, sélectionnez Settings (Paramètres), puis Secrets, puis New repository secret (Nouveau secret de dépôt).

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

  2. Entrez le même nom et la même valeur pour le point de terminaison que ce que vous avez utilisé dans la section précédente. Créez ensuite un autre secret avec le même nom et la même valeur pour la clé que celle utilisée dans la section précédente.

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

11. Exécuter l’application React locale avec la ressource ComputerVision

  1. Redémarrez l’application à partir de la ligne de commande :

    npm start
    

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

  2. Laissez le champ texte vide pour sélectionner une image du catalogue par défaut, puis sélectionnez le bouton Analyze.

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

    L’image est sélectionnée de façon aléatoire dans un catalogue d’images défini dans ./src/DefaultImages.js.

  3. Continuez de sélectionner le bouton Analyze pour voir les autres images et les résultats correspondants.

12. Envoyer (push) la branche locale vers GitHub

Dans le terminal Visual Studio Code, envoyez la branche locale main à votre dépôt distant.

git push origin main

Vous n’avez pas besoin de valider les changements, car aucun n’a été effectué pour le moment.

13. Créer une ressource d’application web statique

  1. Sélectionnez l’icône Azure, cliquez avec le bouton droit sur le service Static Web Apps, puis sélectionnez Créer une application web statique (avancé).

    Visual Studio Code screenshot with Visual Studio extension

  2. Si une fenêtre contextuelle vous demande si vous voulez continuer sur la branche main, sélectionnez Continuer.

  3. Entrez les informations suivantes dans les champs ci-dessous, présentés l’un après l’autre.

    Nom du champ value
    Sélectionnez un groupe de ressources pour les nouvelles ressources. Sélectionnez le groupe de ressources que vous avez créé pour votre ressource ComputerVision, demo-ComputerVision.
    Entrez un nom pour la nouvelle application web statique. Demo-ComputerVisionAnalyzer
    Sélectionner une option de tarif Sélectionnez gratuit.
    Sélectionnez l’emplacement du code de votre application. Sélectionnez la même localisation que celle que vous avez choisie quand vous avez créé votre groupe de ressources, eastus.
    Choisissez Générer une présélection pour configurer la structure de projet par défaut. React
    Choisissez la localisation du code de votre application. /
    Entrez la localisation de votre code Azure Functions. Laissez la valeur par défaut.
    Entrez le chemin de la sortie de votre build relative à l’emplacement de votre application. build

14. Mettre à jour l’action GitHub avec des variables d’environnement secrètes

La clé et le point de terminaison de Vision par ordinateur se trouvent dans la collection de secrets du dépôt, mais ils ne sont pas encore dans l’action GitHub. Cette étape ajoute la clé et le point de terminaison à l’action.

  1. Extrayez les modifications apportées depuis la création de la ressource Azure pour obtenir le fichier d’actions GitHub.

    git pull origin main
    
  2. Dans l’éditeur Visual Studio Code, éditez le fichier d’actions GitHub qui se trouve dans ./.github/workflows/ pour y ajouter les secrets.

    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. Ajoutez et commitez la modification apportée à la branche main locale.

    git add . && git commit -m "add secrets to action"
    
  4. Envoyez la modification au dépôt distant, en démarrant une nouvelle action de génération et de déploiement (build-and-deploy) sur votre application web statique Azure.

    git push origin main
    

15. Afficher le processus de génération GitHub Action

  1. Dans un navigateur web, ouvrez votre dépôt GitHub pour ce tutoriel, puis sélectionnez Actions.

  2. Sélectionnez la build en haut de la liste, puis sélectionnez Build and Deploy Job (Travail de génération et de déploiement) dans le menu de gauche pour regarder le processus de génération. Attendez la fin du travail Build And Deploy.

     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. Afficher le site web statique Azure distant dans le navigateur

  1. Dans Visual Studio Code, sélectionnez l’icône Azure dans le menu tout à droite, sélectionnez votre application web statique, cliquez avec le bouton droit sur Parcourir le site, puis sélectionnez Ouvrir pour afficher le site web statique public.

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

Vous pouvez également trouver l’URL du site ici :

  • le portail Azure pour votre ressource, dans la page Vue d’ensemble.
  • la sortie de la génération et du déploiement de l’action GitHub contient l’URL du site à la fin du script

17. Nettoyer les ressources pour l’application web statique

Une fois que vous avez terminé ce tutoriel, vous devez supprimer le groupe de ressources, qui comprend la ressource Vision par ordinateur et l’application web statique, pour être sûr qu’aucune utilisation supplémentaire ne vous est facturée.

Dans VS Code, sélectionnez l’Explorateur Azure, cliquez avec le bouton droit sur votre groupe de ressources qui est listé sous l’abonnement, puis sélectionnez Supprimer.

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

Code : Ajouter Vision par ordinateur à l’application React locale

Utilisez npm pour ajouter Vision par ordinateur au fichier package.json.

npm install @azure/cognitiveservices-computervision 

Code : ajouter du code Vision par ordinateur en tant que module distinct

Le code de Vision par ordinateur est contenu dans un fichier distinct nommé ./src/azure-cognitiveservices-computervision.js. La fonction main du module est mise en surbrillance.

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

Code : Ajouter un catalogue d’images en tant que module distinct

L’application sélectionne aléatoirement une image dans un catalogue si l’utilisateur n’entre pas l’URL d’une image. La fonction de sélection aléatoire est mise en surbrillance.

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

Code : Ajouter un module de Vision par ordinateur personnalisé à l’application React

Ajoutez des méthodes au fichier app.js de l’application React. L’analyse de l’image et l’affichage des résultats sont mis en surbrillance.

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

Étapes suivantes