Ejercicio: Usar una cuenta de Storage para hospedar un sitio web estático

Completado

Ahora que la API se implementa en la nube, como ingeniero de Tailwind Traders, debe actualizar el código de cliente e implementarlo para admitir los mensajes de SignalR para Azure Functions.

Actualización de la aplicación cliente

  1. En Visual Studio Code, abra ./start/client/src/index.js y reemplace todo el código para escuchar mensajes de SignalR. El código obtiene la lista de existencias inicial con una solicitud HTTP y, a continuación, escucha las actualizaciones de la conexión de SignalR. Cuando se actualiza una acción, el cliente actualiza el precio de las acciones en la interfaz de usuario.

    import './style.css';
    import { BACKEND_URL } from './env';
    
    const app = new Vue({
        el: '#app',
        data() {
            return {
                stocks: []
            }
        },
        methods: {
            async getStocks() {
                try {
    
                    const url = `${BACKEND_URL}/api/getStocks`;
                    console.log('Fetching stocks from ', url);
    
                    const response = await fetch(url);
                    if (!response.ok) {
                        throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
                    }
                    app.stocks = await response.json();
                } catch (ex) {
                    console.error(ex);
                }
            }
        },
        created() {
            this.getStocks();
        }
    });
    
    const connect = () => {
    
        const signalR_URL = `${BACKEND_URL}/api`;
        console.log(`Connecting to SignalR...${signalR_URL}`)
    
        const connection = new signalR.HubConnectionBuilder()
                                .withUrl(signalR_URL)
                                .configureLogging(signalR.LogLevel.Information)
                                .build();
    
        connection.onclose(()  => {
            console.log('SignalR connection disconnected');
            setTimeout(() => connect(), 2000);
        });
    
        connection.on('updated', updatedStock => {
            console.log('Stock updated message received', updatedStock);
            const index = app.stocks.findIndex(s => s.id === updatedStock.id);
            console.log(`${updatedStock.symbol} Old price: ${app.stocks[index].price}, New price: ${updatedStock.price}`);
            app.stocks.splice(index, 1, updatedStock);
        });
    
        connection.start().then(() => {
            console.log("SignalR connection established");
        });
    };
    
    connect();
    
  2. Abra ./start/client/index.html y pegue el código siguiente en lugar de la etiqueta DIV actual con el id. de la aplicación.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css"
            integrity="sha256-8B1OaG0zT7uYA572S2xOxWACq9NXYPQ+U5kHPV1bJN4=" crossorigin="anonymous" />
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css"
            integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
        <title>Stock Notifications | Enable automatic updates in a web application using Azure Functions and SignalR</title>
    </head>
    
    <body>
        <div id="app" class="container">
            <h1 class="title">Stocks</h1>
            <div id="stocks">
                <div v-for="stock in stocks" class="stock">
                    <transition name="fade" mode="out-in">
                        <div class="list-item" :key="stock.price">
                            <div class="lead">{{ stock.symbol }}: ${{ stock.price }}</div>
                            <div class="change">Change:
                                <span
                                    :class="{ 'is-up': stock.changeDirection === '+', 'is-down': stock.changeDirection === '-' }">
                                    {{ stock.changeDirection }}{{ stock.change }}
                                </span>
                            </div>
                        </div>
                    </transition>
                </div>
            </div>
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"
            integrity="sha256-chlNFSVx3TdcQ2Xlw7SvnbLAavAQLO0Y/LBiWX04viY=" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.0/signalr.min.js"></script>
        <script src="bundle.js" type="text/javascript"></script>
    </body>
    </html>
    

    Este marcado incluye un elemento de transición, lo que permite a Vue.js ejecutar una animación sutil a medida que los datos de las acciones cambian. Cuando se actualiza una acción, el icono hace un fundido de salida y rápidamente vuelve a verse. De este modo, si la página está llena de datos de acciones, los usuarios pueden ver fácilmente qué acciones han cambiado.

  3. Agregue el siguiente bloque de script justo encima de la referencia a bundle.js para incluir el SDK de SignalR.

    <script src="https://cdn.jsdelivr.net/npm/@aspnet/signalr@1.0.3/dist/browser/signalr.js"></script>
    

Actualización del archivo .env del cliente

  1. Cree un archivo de variables de entorno en la carpeta start/client denominada .env.

  2. Agregue una variable denominada BACKEND_URL y agregue su valor, que copió de la unidad 5.

    BACKEND_URL=https://YOUR-FUNTIONS-APP-NAME.azurewebsites.net
    

Creación de un recurso de Azure Static Web Apps e implementación de cliente

  1. Abra Azure Portal para crear un nuevo recurso de Azure Static Web Apps.

  2. Use la siguiente información para completar la pestaña Aspectos básicos de la creación de recursos.

    NOMBRE Value
    Suscripción Seleccione su suscripción.
    Resource group Use el grupo de recursos stock-prototype.
    Nombre de la aplicación web estática Posponga el nombre a client. Por ejemplo, client-jamie.
    Tipo de plan de hospedaje Seleccione Gratis.
    Origen de implementación Seleccione GitHub.
    Organización Selección de la cuenta de GitHub
    Repositorio Busque y seleccione mslearn-advocates.azure-functions-and-signalr.
    Sucursal Seleccione la rama main.
    Valores preestablecidos de compilación Seleccione Vue.js.
    Ubicación de la aplicación Escriba /start/client.
    Ubicación de la API Dejar en blanco.
    Ubicación de salida Escriba dist.
  3. Seleccione Vista previa del archivo de flujo de trabajo para revisar la configuración de implementación. El paso Compilar e implementar debe ser similar al siguiente:

    - name: Build And Deploy
      id: builddeploy
      uses: Azure/static-web-apps-deploy@v1
      with:
        azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_123 }}
        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 your app requirements. ######
        # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
        app_location: "/solution/client" # App source code path
        api_location: "" # Api source code path - optional
        output_location: "dist" # Built app content directory - optional
        ###### End of Repository/Build Configurations ######
    
  4. Seleccione Cerrar para guardar el cambio.

  5. Seleccione Revisar y crear y, a continuación, seleccione Crear para crear el recurso. Antes de continuar, espere a que se complete la implementación.

  6. Seleccione Ir al recurso para abrir el nuevo recurso de Azure Static Web App.

  7. En la página Información general, copie el valor de la dirección URL. Esta es la dirección URL base de la aplicación web estática implementada.

Adición de la variable BACKEND_URL al repositorio

El flujo de trabajo debe tener la variable de entorno BACKEND_URL establecida en la dirección URL base de la aplicación de Azure Functions implementada en la unidad 5.

  1. En un explorador para la bifurcación de GitHub del repositorio de ejemplo, seleccione Configuración -> Seguridad -> Secretos y variables -> Acciones.

  2. Seleccione Variables y, a continuación, seleccione Nueva variable de repositorio.

  3. Use la tabla siguiente para crear la variable:

    NOMBRE Valor
    BACKEND_URL Dirección URL base de la aplicación de Azure Functions implementada. La dirección URL debe estar en el formato de https://<FUNCTIONS-RESOURCE-NAME>.azurewebsites.net.
  4. Seleccione Agregar variable para guardar la variable en el repositorio.

Edición del flujo de trabajo de implementación de GitHub

  1. En el terminal de Visual Studio Code, extraiga el nuevo archivo de flujo de trabajo de la bifurcación (origen).

    git pull origin main
    
  2. Abra el archivo .github/workflows/azure-static-web-apps-*.yml .

  3. Cambie el valor name de la parte superior del archivo a Client.

  4. Edite el paso Compilar e implementar para agregar la propiedad env para la variable de entorno BACKEND_URL.

    ```yaml
        name: Client - Azure Static Web Apps CI/CD
        
        on:
          push:
            branches:
              - main
          pull_request:
            types: [opened, synchronize, reopened, closed]
            branches:
              - main
        
        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@v3
                with:
                  submodules: true
                  lfs: false
    
              #Debug only - Did GitHub action variable get into workflow correctly?
              - name: Echo
                run: |
                  echo "BACKEND_URL: ${{ vars.BACKEND_URL }}"
    
              - name: Build And Deploy
                id: builddeploy
                uses: Azure/static-web-apps-deploy@v1
                with:
                  azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_123 }}
                  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 your app requirements. ######
                  # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
                  app_location: "/solution/client" # App source code path
                  api_location: "" # Api source code path - optional
                  output_location: "dist" # Built app content directory - optional
                  ###### End of Repository/Build Configurations ######
                env: 
                  BACKEND_URL: ${{ vars.BACKEND_URL }}
    
          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@v1
                with:
                  azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_123 }}
                  action: "close"
        ```
    
  5. Guarde e inserte los cambios en el repositorio.

    git add .
    git commit -m "Add BACKEND_URL environment variable"
    git push
    
  6. Abra la pestaña Acciones del repositorio de bifurcación de GitHub para ver la implementación.

Actualizar CORS en la aplicación de funciones

De manera predeterminada, las aplicaciones de funciones no permiten solicitudes CORS. Debe actualizar la aplicación de funciones para permitir solicitudes de la aplicación web estática.

  1. En Azure Portal, vaya a la aplicación de Azure Functions creada en la unidad 5.

  2. En el menú de la izquierda, seleccione API:> CORS.

  3. Seleccione Habilitar Access-Control-Allow-Credentials.

  4. Agregue el valor que copió para la dirección URL del recurso de Static Web Apps.

    Propiedad Valor
    Orígenes permitidos Dirección URL base de la aplicación web estática implementada.
  5. Seleccione Guardar para guardar la configuración de CORS.

Prueba de la implementación del cliente

  1. En un explorador, use la dirección URL de la aplicación web estática implementada para abrir el cliente.
  2. Abra las herramientas de desarrollo para ver la consola y ver cuándo se reciben los datos de SignalR sobre las existencias actualizadas. Recuerde que no son solicitudes HTTP, por lo que no las verá en la pestaña Red.

Felicidades. Ha implementado la aplicación de acciones mejorada con SignalR.