本記事はFIXERが提供する「cloud.config Tech Blog」に掲載された「Azure Static Web Apps のローカル実行方法まとめ #Azureリレー」を再編集したものです。
はちゃめちゃ安価にウェブアプリをデプロイできる神サービス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
上記コマンドを順に実行すると、ウェブサーバーが立つはずです。
開いてみると、いつもの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ファイルを追加します。
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 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の値を取得して表示するようにします。
App.vue
<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ファイルを編集します。
こちらはご存じの通りローカル実行時のみ有効になるのでとりあえず全部通しておきます。
local.setting.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の向き先を変更します。
App.vue
~前略~
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プロジェクトのルートで以下のコマンドを叩いてフロントのサーバーを立てます。
ターミナル1
npm run serve
続いて、APIのフォルダで以下のコマンドを叩いてAPIサーバーを立てます。
ターミナル2
func start
ここで、上記ターミナル1、2に表示されているURLを確認します。
フロントのURLが「http://localhost:3000」でAPIのURLが「http://localhost:7071/api/Function」だったとします。
すると、SWAを実行するコマンドは以下のようになります。
ターミナル3
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はほかに実行しているアプリケーションとポートが被るとひとつずらすだけ(=エラーが出ない)なため、意図せず他のアプリケーションにルーティングしてしまう恐れがあります。
そのため被らない番号をおススメします。
Package.json
~前略~
"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
佐藤 晴輝/FIXER
フロントからバック、ネットワークまである程度触れるガジェットオタクです。
好きな言語は C# で IoT と画像処理が得意です。