練習 - 使用儲存體帳戶來裝載靜態網站

已完成

現在 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 取代為應用程式的識別碼。

    <!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. 在名為 .envstart/client 資料夾中建立環境變數檔案。

  2. 新增名為 BACKEND_URL 的變數,並新增您從單元 5 複製的值。

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

建立 Azure 靜態 Web 應用程式資源並部署用戶端

  1. 開啟 Azure 入口網站,以建立新的 Azure Static Web Apps 資源。

  2. 使用下列資訊來完成資源建立 [基本資料] 索引標籤。

    名稱
    訂用帳戶 選取您的訂用帳戶。
    資源群組 使用資源群組 stock-prototype
    靜態 Web 應用程式名稱 將名稱貼到 client。 例如: client-jamie
    主控方案類型 選取 [免費]
    部署來源 選取 [GitHub]
    Organization 選取您的 GitHub 帳戶
    存放庫 搜尋和選取 mslearn-advocates.azure-functions-and-signalr
    分行 選取 main 分支。
    組建預設 選取 [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 環境變數的 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. 新增您為 Static Web Apps 資源 URL 複製的值。

    屬性
    允許的原始來源 已部署靜態 Web 應用程式的基底 URL。
  5. 選取 [儲存] 以儲存 CORS 設定。

測試用戶端的部署

  1. 在瀏覽器中,使用已部署靜態 Web 應用程式的 URL 來開啟用戶端。
  2. 開啟開發人員工具來監看主控台,以查看何時收到更新股票的 SignalR 資料。 請記住,這些不是 HTTP 要求,因此您將不會在 [網路] 索引標籤中看到。

恭喜! 您已部署了使用 SignalR 改善過的股票應用程式!