Azure Static Web Appsで短時間でWEBアプリを公開する


前置き

2021年 5月にAzure Static Web Appsが正式にGA(一般公開)されました。
私は普段よく業務でVue.jsを使っているのですが、Azureでホスティングする際、今まではストレージアカウントのBlob StorageやApp Serviceを利用していましたが、この度専用のサービスがリリースされるということで使い方を試してみました。

前提条件

本記事ではVue.jsを使用してWebアプリケーションを構築します。
また、素早くアプリケーションを構築するためVue CLIを使用します。
バージョン管理ツールはGitHubを使用します。

それぞれのバージョンについては下記の通りです。
Vue.js:2.6.14
Vue CLI:4.5.13
npm:7.18.1

Azure Static Web Appsとは

Azure Static Web Apps は、GitHubやAzure DevOpsのリポジトリから
Webアプリケーションを自動的にビルド&デプロイするサービスです。

主要な機能は以下の通りです。

  • HTML、CSS、JS、画像等の静的コンテンツのWebホスティング
  • リポジトリの変更によってビルドとデプロイがトリガーされるGitHub統合およびAzure DevOps統合
  • Azure Functionsとの統合を標準サポート
  • APIの呼び出し時のCORSの構成が不要
  • リポジトリの変更をトリガーにビルドからデプロイまで実行されるCI/CD環境を提供
  • グローバルに分散された静的コンテンツがユーザーに近いリージョンに配置される
  • 自動的に更新される無料のSSL証明書を使用可能
  • カスタムドメインを設定可能
  • Azure AD、GitHub、Twitter等の認証プロバイダーとの統合を標準サポート
  • カスタマイズ可能な認可ロールの定義と割り当て
  • 提供するコンテンツとルートを完全に制御できるようにするバックエンド ルーティング規則
  • プルリク時に、デプロイ前のサイトのプレビュー状態を確認可能

Static Web Appsの構成図

下図はStatic Web Appsの構成図になります。
リポジトリのコード変更をトリガーに、Build&Deployのワークフローが実行されてStaic Web Appsに反映されるイメージです。

WEBアプリケーションをホスティングする

まずはWEBアプリのホスティングを試してみます。

  • GitHubにリポジトリ(リポジトリ名:static-web-apps)を作成する。
  • ローカルにリポジトリをクローンする。
  • Vue CLIを使って土台となる環境を準備する。
    ※vuetifyは必要であれば追加する。
cd static-web-apps
vue create .
vue add vuetify
npm i
  • 作成した土台をローカルホストで確認する。

    npm run serve
    Vue CLIで作成した土台となるアプリケーション

  • mainブランチにソースをpushする。

git add --all
git commit
git push origin main
  • Static Web Appsのリソースを作成する。
  • Azure Functions APIとステージング環境のリージョンはEast Asiaを選択する。
  • プランはFreeプランを選択する。
  • 「GitHubアカウントでサインイン」ボタンを押下する。
  • 「Authorize Azure-App-Service-Static-Web-Apps」のボタンを押下する

各項目に以下の値をそれぞれ設定する。
組織:リポジトリを作成した組織
リポジトリ:作成したリポジトリ
分岐:main
ビルドのプリセット:Vue.js
アプリの場所:/
APIの場所(※後で使用します):api
出力先:dist

  • GitHub Actionsのワークフローの状態を確認する。
  • ワークフローが完了後Static Web Appsの[概要]から発行されたURLを確認する。
  • 正常にアプリケーションが表示されたらホスティング完了です。

Azure Functionsと統合する

次にStatic Web AppsはAzure Functionsとの統合を標準でサポートしているので、
APIを実装してWebアプリと疎通できるか試してみます。

  • ルート階層でapiディレクトリを作成する。
  • VsCodeのAzure Functionsの拡張機能を使ってHttpTrigerの関数を作成する。
    F1キーでコマンドパレットを開いてcreate new projectからapiディレクトリを指定する。
    javascript → HttpTrigger → 関数名入力 → Anonymousの順番で設定を進めます。
  • 今回はGETのAPIのみ作成するので、api/HttpTrigger1/function.jsonのmethodsからpostを削除する。
{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get",
        "post" ←削除
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}
  • APIのURLの設定のためapi/HttpTrigger1/function.jsonのrouteを設定する。
{
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "get"
      ],
      "route": "msg" ←追加
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

※この場合のAPIのurlは/api/msgになる

  • ローカル環境でAPIを実行するために以下の設定を行う

api/local.settings.jsonにCORSの設定を追記

"Host": {
  "CORS": "http://localhost:8080"
}

○ vue.config.jsにプロキシ設定を追記

devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:7071'
      }
    }
  }
  • API実行に必要なライブラリをインストールする
npm i vue-axios
npm i axios
  • アプリケーション側を編集してAPIを呼び出す処理を追記する

main.jsにaxiosのimport設定を追記

main.js
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import axios from 'axios' // 追記
import VueAxios from 'vue-axios' // 追記

Vue.config.productionTip = false

Vue.use(VueAxios, axios) // 追記

new Vue({
  vuetify,
  render: h => h(App)
}).$mount('#app')

HelloWorld.vueの内容を編集してAPIを実行するUIに変更

HelloWorld.vue
<template>
  <v-container fluid>
    <v-row justify="center">
      <v-col cols="4">
        <v-card>
          <v-card-text>
            <v-row>
              <v-col cols="12">
                <v-text-field
                  v-model="name"
                  outlined
                  hide-details
                >
                </v-text-field>
              </v-col>
              <v-col v-show="msg" cols="12">
                {{ msg }}
              </v-col>
            </v-row>
          </v-card-text>
          <v-card-actions>
            <v-btn
              @click="getMsg"
              color="primary"
              dark
              block
            >
              メッセージ取得
            </v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
  export default {
    name: 'HelloWorld',

    data: () => ({
      name: '',
      msg: ''
    }),
    methods: {
      async getMsg () {
        this.msg = await this.axios.get(`api/msg?name=${this.name}`).then(res => res.data)
      }
    }
  }
</script>

  • ローカル環境でAPIが実行可能か確認する。
    2つコンソールを起動して片方でnpm run serveを実行してアプリケーションを起動する。 もう片方はapi配下に移動後にfunc startを実行してAPIを起動する。

編集後のアプリケーション
テキストボックスにいれた文字列をクエリーに設定して、GETのAPIを実行した結果を画面に表示するアプリケーション

  • mainブランチに編集後のソースをpushする。
  • GitHub Actionsのワークフローの状態を確認する。
  • ワークフロー完了後、Static Web Appsの[関数]に追加したAPIが表示されているか確認する。

  • static web appsの[概要]から発行されたURLを確認する。
    ※APIが正しく実行できるかを確認する。

ステージング環境を準備する

Static Web Appsでは本番環境にデプロイする前に、
ステージング環境のプレビューURLを発行して動作確認を行うことができるのでこの機能も試してみます。

  • stagingブランチを作成する
git branch staging
git switch staging
  • stagingブランチでアプリケーションのソースを変更する。

ボタンの色をピンク色に変更してみます。

HelloWorld.vue
<v-btn
  @click="getMsg"
  color="pink" ボタンの色をピンク色に変更
  dark
  block
>
  メッセージ取得
</v-btn>
  • stagingブランチにソースをpushする。
  • mainブランチに対するプルリクエストを作成する。

  • GitHubアクションのワークフローの状態を確認する。

  • プルリクエストページに表示されるプレビューURLを参照する。

プレビューURLの結果(ボタンの色を変更している)

※Static Web Appsの[環境]からもstaging環境を参照することができます。

価格設定

参考までにStatic Web Appsの価格設定のURLを記載します。
カスタム認証や、SLAが不要であれば基本的には無料枠で必要な機能を試すことが可能です。

Static Web Apps の価格

参考

Azure Static Web Apps のドキュメント