Azure Static Web Apps
ついに、一般提供を開始しました! azure.microsoft.com
サポート エンジニア時代にいたチームはこの製品も担当していたので、割と早い段階 (パブリック プレビュー開始の前あたり) から知っている製品でした。
でも正直「静的ファイルや SPA のホスティングなんて、Web Apps でやったらいいじゃない」と思い、あまり本腰入れて試していませんでした (ごめんなさい💦)。
が、ある程度試していく中で、Web フロントエンドに特化した製品であることが理解でき、「なるほど便利だ」とひとしきり反省しております。
確かに Web Apps だけで SPA をホスティングしようとして、ハマることもあるんですよね。
uncaughtexception.hatenablog.com
今もこの問題が残っているか確認してませんが、ビルド周りの違いだけではなく、Azure Static Web Apps はグローバル サービスなので、常にクライアントに最も近いエッジ サーバーから配信される、というメリットもあります。
SPA に特化したホスティングにはオススメですね。
# Web Apps も大好きです。適材適所です。
その他の機能、日本語ではこちらの三宅さんのブログ、公式ドキュメントに網羅されているので、興味のある方はこちらをご覧ください。
本題
Static Web Apps 猛者の三宅さんのツイートを発端に疑問が。
もしかして #codespaces 使えば、VSCode もいらないですかね?
— ほりひろ loves <⚡> (@hori__hiro) 2021年5月13日
ということで、
GitHub Codespaces/Web ブラウザーだけを使って、Azure Static Web Apps に載せる SPA と Serverless API の開発/デバッグができるか
を試してみました。
GitHub Codespaces
ざっくりいうと、
Web ブラウザー上で、VSCode 風(というかそのもの)な UI で、GitHub リポジトリーのファイルを直接?編集できる
というものです。
GiHub Codespaces を使えば、コーディングはできます。
あと GiHub Codespaces からリポジトリーに直接 git push ができるので、GitHub Actions 経由で Azure Static Web Apps へのコードのデプロイもできます。
では、デバッグはどうなのか。
結論
- SPA の Javascript は、Web ブラウザーの開発者ツール
- バックエンドの Serverless API は、GiHub Codespaces の Dev Container 上の Azure Functions Core Tools
さらに GiHub Codespaces の Dev Container 上で Static Web Apps CLI を動かして、認証関連の動きもエミュレートできるようになります。
tasks.json
GitHub Codespaces はデバッグ機能もほぼ VSCode なので、.vscode/tasks.json
に個々の task を書いていけば VSCode 同様にデバッグ実行ができます。
SPA ビルド用 task
プロジェクト ルートで npm run build
しています。vue であれば vue-cli-service build
が実際のコマンドになります。
{ "type": "shell", "label": "npm run build", "command": "npm run build", "dependsOn": "npm install (for app)", "options": { "cwd": "${workspaceFolder}" } },
あと webpack でのビルド設定などで、source map を出力するようにします。
これでブラウザーの開発者ツール上で Break point が設定できます。
vue であれば、vue.config.js
に下記の configureWebpack
設定を追加をしておきます。
module.exports = { // : configureWebpack: { devtool: 'source-map' }, // : }
この task はビルド結果 (バンドルされた JS ファイルなど) を ./dist
などに出力して終了です。
# Webpack Dev Server を使ってない (vue-cli-service serve
してない) 理由は後述
バックエンド Serverless API デバッグ開始 task
Azure Functions Core Tools でバックエンドの Serverless API をデバッグ実行します。
./api
に Azure Functions のプロジェクトがあるとして、そこで func host start
を実行しています。
オプション --language-worker -- \"--inspect=9229\"
を追加して、GitHub Codespaces 上のデバッグ プロセスから Launguage Worker プロセスにアタッチできるようにしています。
{ "type": "shell", "label": "func start", "command": "func host start --language-worker -- \"--inspect=9229\"", "problemMatcher": { "owner": "custom", "pattern": { "regexp": "^$" }, "background": { "activeOnStart": true, "beginsPattern": "^.*(Job host stopped|signaling restart).*$", "endsPattern": "^.*(Worker process started and initialized|Host lock lease acquired by instance ID).*$" } }, "isBackground": true, "dependsOn": "npm install (for api)", "options": { "cwd": "${workspaceFolder}/api" } },
この task を実行すると、通常の Azure Functions プロジェクトのデバッグと同様、http://localhost:7071
動作し続けます。
Static Web Apps CLI 起動用 task
npm run build
で出力した ./dist
を Static サイトに、func host start
で動かした http://localhost:7071
をバックエンド API に指定して、Static Web Apps CLI を実行しています。
# npm script に引数を渡すために --
が必要、ということをここで知りました。
{ // "type": "shell", "label": "swa start", "command": "npm run swa -- start dist --api=http://localhost:7071", "isBackground": true, "problemMatcher": { "owner": "custom", "pattern": { "regexp": "^$" }, "background": { "activeOnStart": true, "beginsPattern": "^.*Using dev server for static content .*$", "endsPattern": "^.*Azure Static Web Apps emulator started.*$" } }, "dependsOn": [ "npm run build", "func start" ], "options": { "cwd": "${workspaceFolder}" } },
dependsOn
で上の 2 つの task を指定しているので、これらの task が完了状態になってから実行しています。
launch.json
上のタスクを実行する GitHub Codespaces のデバッグ設定は、Azure Functions 用の設定をマルっとパクります。
{ "name": "Launch Static Web Apps Dev Server and Backend Functions", "type": "node", "request": "attach", "port": 9229, "preLaunchTask": "swa start" }
これで GitHub Codespaces がバックエンド Serverless API のデバッグ プロセスにアタッチします。
その他
Dev Container で Azure Functions Core Tools を入れたり、devDendencies
の一つとして Static Web Apps CLI を入れたりしてますが、まとめたものはこちらにあるので興味があれば。
動作の様子
デバッグ実行の様子はこちら。
Developing #StaticWebApps on GitHub #Codespaces using Azure Functions core Tools, Static Web Apps CLI, and #vue-cli (2/2) Debug vue-app, functions and authentication process pic.twitter.com/0lYbcsIDlv
— ほりひろ loves <⚡> (@hori__hiro) 2021年5月14日
Dev Container 内の Static Web Apps CLI のサーバー プロセスには、
https://${ユーザー名/組織名}-${リポジトリー名}-${4桁のランダム文字列}-${フォワード先のポート番号}.githubpreview.dev/
という URL でアクセスできます。
PORTS
のリストに URL が出てくるので、Static Web Apps CLI は 4280 で待ち受けているので、それにフォワードしている URL を選びましょう。
現時点でわかっているできないこと
実はいくつかのことが、このデバッグ構成ではできません。
ログアウト時のルーティング
この GitHub Codespaces の構成でログアウト (/.auth/logout
にアクセス) すると、必ず http://localhost
にリダイレクトされます。
当然、ローカルでサーバーを実行していなければエラー画面が表示されます。
どうやら、上の URL へのリクエストは Dev Container 内の Static Web Apps CLI のプロセスに届く前にリバース プロキシを通っているようで、リクエストの host
ヘッダーには localhost
、本来リダイレクト先に使いたい上の URL のホスト名は x-forwarded-host
ヘッダーに入ってきます。
一方で、Static Web Apps CLI の開発サーバーのログアウト時のリダイレクト先は、以下のように host
ヘッダーだけを見ているので、http://localhost
にリダイレクトされるようです。
const host = req?.headers?.host;
PR は出していますが、このリバース プロキシ環境でのデバッグ、ということ自体が想定外な気がするので、マージされるか怪しいですね。
SPA の Hot reload
SPA 用の task で、npm run serve
(Webpack Dev Server でのホスティング) ではなく npm run build
で ./dist
にバンドルされた JS ファイル作成していました。
なので、SPA 側のファイルを更新しても、自動でリロードしてくれません。
当然、SPA 側を npm run serve
で WebPack dev server で起動し、Static Web Apps CLI も npm run swa -- start http://localhost:8080 --api=http://localhost:7071
のように実行すると Hot Relaod が可能になります。
ただし、Static Web Apps CLI の現在の動作として、Dev Server を使った場合に staticwebapp.config.json
をロードしないので、認証や独自のルーティングが動きません。
Static Web Apps CLI のルーティングを改善しようとしているそうなので、それと合わせて改善されるようです。
ただ、GitHub Codespaces の場合、ちょっとした変更でもファイルは自動で保存されるので、その度に Hot Relaod が動くのもどうかと思うので、Hot Relaod ではなく都度手動で npm run build
を実行する方がいい気もします。
このあたりは、ファイル保存のタイミングをコントロールできるローカル環境と違いが出る部分ですね。
以上、だいぶニッチにエントリーでした。