练习 - 使用存储帐户托管静态网站

已完成

现在,API 已部署到云端。作为 Tailwind Traders 的工程师,您需要更新客户端代码并将其部署,以支持用于 Azure Functions 的 SignalR 消息。

更新客户端应用程序

  1. 在 Visual Studio Code 中,打开 ./start/client/src/index.js 并替换所有代码以侦听 SignalR 消息。 该代码使用 HTTP 请求获取初始库存列表,然后从 SignalR 连接侦听更新。 更新股票后,客户端会在 UI 中更新股票价格。

    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. 打开 ./start/client/index.html 并粘贴以下代码,将当前 DIV 替换为应用的 ID。

    <!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>
    

    此标记包括一个过渡元素,该元素允许 Vue.js 在股票数据更改时运行细微的动画。 股票更新时,该磁贴淡出并迅速恢复可见。 这样,如果页面包含股票数据,用户可以轻松查看哪些股票发生了变化。

  3. 将以下脚本块添加到引用的正上方以包含 SignalR SDK bundle.js

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

更新客户端 .env

  1. start/client文件夹中创建一个名为.env的环境变量文件。

  2. 创建一个名为BACKEND_URL的变量,并添加从单元5复制过来的其值。

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

创建 Azure 静态 Web 应用资源并部署客户端

  1. 打开 Azure 门户 以创建新的 Azure 静态 Web 应用资源。

  2. 使用以下信息填写资源创建页面上的“基本信息”选项卡

    名称 价值
    订阅 选择订阅。
    资源组 使用资源组 stock-prototype
    静态 Web 应用名称 将名称追加到 client 后面。 例如,client-jamie
    托管计划类型 选择“免费”。
    部署源 选择“GitHub”。
    组织 选择 GitHub 帐户
    存储 库 搜索并选择 mslearn-advocates.azure-functions-and-signalr
    分支 选择主分支。
    生成预设 选择 Vue.js
    应用位置 输入 /start/client
    API 位置 留空。
    输出位置 输入 dist
  3. 选择 “预览”工作流文件 以查看部署设置。 生成和部署步骤应如下所示:

    - 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. 选择 “关闭 ”以保存更改。

  5. 选择 “查看 + 创建”,然后选择“ 创建 ”以创建资源。 等待部署完成,然后继续。

  6. 选择 “访问资源” 以打开新的 Azure 静态 Web 应用资源。

  7. “概述 ”页上,复制 URL 值。 此值是已部署的静态 Web 应用的基 URL。

将BACKEND_URL变量添加到存储库

工作流需要将 BACKEND_URL 环境变量设置为单元 5 中部署的 Azure Functions 应用基 URL。

  1. 在示例存储库的 GitHub 分支的浏览器中,选择设置 -> 安全性 -> 机密和变量 -> 操作

  2. 选择 “变量”,然后选择“ 新建存储库变量”。

  3. 使用下表创建变量:

    名称 价值
    BACKEND_URL 已部署的 Azure Functions 应用的基本 URL。 URL 的格式应为 https://<FUNCTIONS-RESOURCE-NAME>.azurewebsites.net
  4. 选择 “添加变量 ”,将变量保存到存储库。

编辑 GitHub 部署工作流

  1. 在 Visual Studio Code 终端中,从分支(源)中拉取新的工作流文件。

    git pull origin main
    
  2. 打开 .github/workflows/azure-static-web-apps-*.yml 文件。

  3. name 文件顶部的值更改为 Client

  4. 编辑“生成和部署”步骤以添加环境变量的 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. 保存更改并将其推送到存储库。

    git add .
    git commit -m "Add BACKEND_URL environment variable"
    git push origin main
    
  6. 在 GitHub 分支存储库中打开 “操作” 选项卡,以监视部署。

在函数应用中更新 CORS

默认情况下,函数应用不允许 CORS 请求。 需要更新函数应用以允许来自静态 Web 应用的请求。

  1. 在 Azure 门户中,导航到在单元 5 中创建的 Azure Functions 应用。

  2. 在左侧菜单中,选择 API -> CORS

  3. 选择 “启用访问控制-允许凭据”。

  4. 添加你为静态 Web 应用资源 URL 复制的值。

    资产 价值
    允许的域 已部署的静态 Web 应用的基 URL。
  5. 选择 “保存” 以保存 CORS 设置。

测试客户端的部署

  1. 在浏览器中,使用已部署的静态 Web 应用的 URL 打开客户端。

  2. 在 Azure 门户中,打开开发人员工具并监视控制台,以查看何时收到更新股票的 SignalR 数据。 请记住,SignalR 数据不是 HTTP 请求,因此更新不会显示在“网络”选项卡中。

祝贺! 你已部署了通过 SignalR 改进的股票应用!