Azure Static Web Apps のローカル実行方法まとめ #Azureリレー

はちゃめちゃ安価にWebアプリをデプロイできる神サービス Azure Static Web Apps (SWA) 。

以前はその魅力をお伝えしましたが、今回は実際に Static Web Apps を使って開発する際のローカル実行方法についてご紹介します。

公式のリファレンスはだいぶしっかりしているものの、対応しているフレームワークが多すぎてふんわりした書き方になっている部分が多いです。

そこで今回は、「Vue.js」のフロントと「.NET Core 3.1」のAPI という組み合わせで実際に実行する流れをご紹介します。

この流れを確認した上で公式リファレンスを読めばどんな環境でも動かせること間違いなし!?

本記事で用いたバージョン

npm :8.1.0

node : v16.13.0

.NET Core SDK :3.1.415

Azure Functions Core Tools: 3.0.3904

ターミナル:PowerShell

準備

フロントアプリの用意

vue-cli を使ってサクッと立てます

npm install -g @vue/cli
vue create test-site
cd test-site
npm run serve

上記コマンドを順に実行すると、Webサーバーが立つはずです。

開いてみると、いつもの Vue のデフォルトサイトが表示されます。

APIサーバーの用意

続いて、APIです。

こちらも Azure Functions Core Tools を使ってサクッと立てます。

Azure Functions Core Tools は事前にMSからダウンロード&インストールしておく必要もあるようなのでご注意ください。

npm install -g azure-functions-core-tools@3
func init BlogFunction

上記コマンドで作成されたフォルダに Function.cs ファイルを追加します。

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;

namespace BlogFunction
{
    public static class Function
    {
        [FunctionName("Function")]
        public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            return new OkObjectResult(new{api_response= "APIを叩けたよ!"});
        }
    }
}

とりあえずJSON形式で文字列を返すだけのファンクションです。

cd .\BlogFunction\
func start

実行するとURLが一つ表示されるはずなので開くと、上記の通りAPIから値が取得できていることがわかります。

フロントからAPIを呼び出す

Vue のデフォルトアプリを修正してAPIの値を取得して表示するようにします。

<template>
  <div id="app">
    <h2>{{str}}</h2>
    <HelloWorld msg="Welcome to Your Vue.js App"/>    
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data: function(){
    return {
      str:"APIを叩けなかったよ……"
      }
  },
  created:async function(){
    const res = await fetch("http://localhost:7071/api/Function");
    const result = await res.json();
    if(result){
    this.str=result.api_response;
    }
  }
}
</script>

~後略~

Functions のCORS設定を変更するため、local.settings.json ファイルを編集します。

こちらはご存じの通りローカル実行時のみ有効になるのでとりあえず全部通しておきます。

{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet"
    },
    "Host": {
        "CORS": "*"
      }
}

Functions のサーバーを立てた状態でフロントのサーバーを立ててアクセスします。

API が叩けていることがわかります。

確認のため、Functions のサーバーを閉じた後にアクセスします。

APIが叩けないことがわかります。

Azure Static Web Apps のローカル実行!

static-web-apps-cli のインストールと最もシンプルに実行する!

Static Web Apps (SWA) のローカル実行に必要な static-web-apps-cli をインストールします。

最も素朴な実行方法のために、vueプロジェクトを予めビルドして静的なサイトとして出力しておきます。

vue のデフォルト出力先はdistフォルダになります。

npm install -g @azure/static-web-apps-cli
npm run build
cd dist
swa start

先ほどとは違うポートが使われているURLが表示されるのでアクセスします。

先ほどのままAPIサーバーを閉じている場合にはAPIを叩けないはずです。

ここで、SWA に対応するために Vue プロジェクトからのAPIの向き先を変更します。

~前略~
  created:async function(){
    const res = await fetch("/api/Function"); //この行を書き換えました!!!!
    const result = await res.json();
    console.log(result)
    if(result){
    this.str=result.api_response;
    }
  }
~後略~

vue プロジェクトのルートフォルダに移動し、再度ビルドします。

続いて、先ほどとは少し違うコマンドで SWA をローカル実行します。

cd ../
npm run build
swa start .\dist\ --api-location ..\BlogFunction\

再度表示されたURLにアクセスすると今度はAPIが叩けているはずです!

static-web-apps-cli を使いこなしてデバッグ実行する!!

先ほどの方法では実行するたびにビルドしなおす必要があり、非常に面倒です。

また vue の強みの一つであるホットリロードにも対応しておらず、細かい変更のたびに再実行する必要があります。 

そこで、自分で立てたフロントのサーバーを SWA にルーティングしてもらうように設定します。

まず、vue プロジェクトのルートで以下のコマンドを叩いてフロントのサーバーを立てます。

npm run serve

続いて、APIのフォルダで以下のコマンドを叩いてAPIサーバーを立てます。

func start

ここで、上記ターミナル1,2に表示されているURLを確認します。

フロントのURLが「http://localhost:3000」でAPIのURLが「http://localhost:7071/api/Function」だったとします。

すると、SWAを実行するコマンドは以下のようになります。

	swa start http://localhost:3000 --api-location http://localhost:7071

上記を実行して表示されるURLにアクセスすると、APIが叩けているはずです。

また、vue のコンポーネントを編集して保存するとホットリロードが起動して表示が切り替わります。

vue-cli を拡張してワンコマンドでデバッグ実行できるようにする!!!

上記の手段は便利なのですが、コマンドを複数ターミナルを用いて実行しないといけないのが面倒です。

そこで、vue-cli を拡張してワンコマンドで実行できるようにします。

package.json に加筆して、swaコマンドを追加します。

また、serveコマンドでportを指定するようにしておきます。

ここで指定するportはswaコマンドの方と一致していればなんでもよいです。

しかし、npmはほかに実行しているアプリケーションとポートが被ると1つずらすだけ(=エラーが出ない)なため、意図せず他のアプリケーションにルーティングしてしまう恐れがあります。

そのため被らない番号をおススメします。

~前略~
  "scripts": {
    "serve": "vue-cli-service serve --port 8180",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "swa": "swa start http://localhost:8180 --run \"npm run serve\"  --api-location=../BlogFunction   --api-port=7071"
  },
~後略~

これでワンコマンドでSWAが実行できるようになりました。

npm run swa

もしターミナルに表示されているURLのポートが先ほど自身が指定したもの(例だと8180)だった場合には起動に失敗しているので一度閉じて再度実行してください。

もし何度も実行に失敗する場合はAPIサーバーが立てらない可能性があるのでswaコマンド内のPathを確認したり、func start コマンドでAPIサーバーが立つことを確認してください。

まとめ

SWAは新しいサービスだけあって用意されている機能もユーザーの気持ちを分かっているものが多いと感じます。

「ここ不便だなぁ」と思っても、探してみれば解決策が用意されているかもしれません。

本記事は実際にその流れで解決した例になります。

みなさんも本記事と公式リファレンスを参考に、Static Web Apps を使ってみてくださいね!

(おまけ) SWA と CORS

SWAを用いるとオリジンが統一されるので、フロント-API間でCORSが問題になりません。

つまり、「とりあえず全通し」みたいなセキュリティリスクをなくすことができるのです。

本記事中ではlocal.settings.jsonで行ったCORSの設定を削除しても問題なくAPIが叩けることで確かめることができます。

参考

Azure Static Web Apps 用にローカル開発環境を設定する | Microsoft Docs