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

已完成

将 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. 在对 bundle.js 的引用上方添加以下脚本块以包含 SignalR SDK

    <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 Static Web Apps 资源并部署客户端

  1. 打开 Azure 门户以创建新的 Azure Static Web Apps 资源。

  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 Static Web Apps 资源

  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 环境变量添加 env 属性

    ```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
    
  6. 打开 GitHub 分支存储库中的“操作”选项卡以观察部署

在函数应用中更新 CORS

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

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

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

  3. 选择“启用 Access-Control-Allow-Credentials”

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

    属性
    允许的源 已部署的静态 Web 应用的基 URL。
  5. 选择“保存”以保存 CORS 设置

测试客户端的部署

  1. 在浏览器中,使用已部署的静态 Web 应用的 URL 打开客户端。
  2. 打开开发人员工具来观察控制台,看看何时收到了已更新的股票的 SignalR 数据。 请记住,这不是 HTTP 请求,因此它们不会显示在“网络”选项卡中。

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