SPAをStatic Web Appsにデプロイ、本番環境で使ってみた

MicrosoftのカンファレンスMS Build 2020でAzure Static Web Appsが発表され、同時期にちょうどSPA（Single Page Application）でウェブアプリケーションを開発中だったので、まだPreview中でしたが、GitHub Actionsとの連携もできそうだったので、ぜひプロダクションで使おう！と思い現在進行形で運用しています。
なので、私みたいにHTML、CSS、JavaScript等の静的コンテンツを本番環境で運用しようとしている方向けに**「Static Web Appsは使えるのか？」**という記事を書きたいと思います。

#本番環境で動かしてみた所感
先に結論を言うと、**Static Web Apps** 十分使えます。様々気づきもあったので紹介していきます。まずは出来上がったものをお見せすると以下のサイトです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【拡散希望！】<br>留学希望者には絶対見てほしい「日本初！AIを使った最強留学情報サイト」ついに完成しました！自信を持ってマジヤバすごいサイトになりました。ぜひ一度見て見てください！<br><br>New サイト:<a href="https://t.co/hZmJDG4Kyb">https://t.co/hZmJDG4Kyb</a><a href="https://twitter.com/hashtag/%E7%95%99%E5%AD%A6?src=hash&amp;ref_src=twsrc%5Etfw">#留学</a> <a href="https://twitter.com/hashtag/%E7%95%99%E5%AD%A6%E7%94%9F?src=hash&amp;ref_src=twsrc%5Etfw">#留学生</a> <a href="https://twitter.com/hashtag/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E7%95%99%E5%AD%A6?src=hash&amp;ref_src=twsrc%5Etfw">#アメリカ留学</a> <a href="https://t.co/EX7otDPhdg">pic.twitter.com/EX7otDPhdg</a></p>&mdash; Kei Otoi Okada (@KeiOtoiOkada) <a href="https://twitter.com/KeiOtoiOkada/status/1298079574866030592?ref_src=twsrc%5Etfw">August 25, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こちらのサイト、留学希望者が大学を選ぶ際に、より具体的な情報を得て多くの人が留学に行ってほしい！って想いで作成しました。そうです、こちらのサイトのフロント側（静的コンテンツ部分）が丸っとStatic Web Appsに乗っかって今も現在進行形で本番環境で動いています。

#Azure Static Web Appsとは

いわゆるSPA(Single Page Application)やらSSG(Static Site Generator)やらを含むHTML、CSS、JavaScript等の静的コンテンツを配信する新しいAzureサービスです。その他にもカスタムドメインやSSL証明書が無料で設定できたり、Azure Functionsと統合できたり（今回は使ってませんが）、その他もろもろ非機能要件にもしっかり対応してくれています。
また今回使いたい！と思わせてくれた機能のひとつで、ビルド環境としてGitHub Actionsが強制的に使われるように設定されているため、コンテンツを更新する度にビルドを走らせるJAMstack運用も可能となっています。

[Azure Static Web Appsの公式サイトはこちら](https://azure.microsoft.com/ja-jp/services/app-service/static/)

#今回の構成
インフラの運用、管理するのは絶対に嫌だ！ということで考え付く最高のPaaS（Platform as a Services）を採用（Static Web Appsに関してはまだPreviewだが）しました。これでやりたくないインフラの管理はなくなり、また将来の拡張性も考え（モバイルアプリも作るかもだから）フロントエンドとバックエンドを分けて構築しました。以下が構成図です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/ba440b0f-1fb2-5d5e-eef6-0f1d69ec07f3.png)

1. ウェブアプリケーションのフロントエンドはReactを使いTypeScriptで書いています（**今回はこの部分の話しかしません**）
2. ウェブアプリケーションのバックエンドは.NET Coreを使いC#で書いています
3. データベースはSQL DBを使用しています

#Static Web Appsにデプロイ完了するまでの手順（軽く）
実際のデプロイ完了する手順は以下の記事に良く書かれているのでそちらを参照していただければなと思います。
[たぶん10分で試せる。Azure Static Web AppsにWebサイトをデプロイして独自ドメイン設定とFunctionsでAPI公開まで](https://qiita.com/n0bisuke/items/1e12d8abb76d40a83fea)

**一応簡単に手順だけは紹介します。**
1. GitHubリポジトリを作成し、ソースコードをPush
2. Azureポータル上でStatic Web Appsを作成し、先ほど作ったGitHubのリポジトリを参照させる
3. GitHubのリポジトリ上にgitHub/workflowsのフォルダーが自動的に作成され、ビルド＆デプロイの手順が書かれたymlファイルが自動生成される
4. カスタムドメイン購入＆ポータルで設定

正直驚くほど簡単にデプロイが完了します。リアルに10分ぐらいで完了してしまいます。

#Static Web Appsで運用してみて良かったと感じたところ
今のところ問題なく本番環境でも動いていて、Previewだがかなり良く出来ている印象。以下良かった点まとめています。

- グローバルコンテンツディストリビューションを使用
- Static Web Apps作成する際、自動的にビルド＆デプロイの手順が書かれたymlファイルを定義してくれる
- Static Web Appsのルーティング定義は *routes.json* で記述すれば問題なし
- やっぱり**無料**は助かる

##グローバルコンテンツディストリビューションを使用
**全世界のApp Service内にデプロイ + Traffic Manager**で近くのApp Serviceにルーティングしているらしく、高可用性はかなり期待できるかと。

以下が公式のサイトの説明です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/f1a8211b-6013-1ea1-f463-68cf3e1b552e.png)

一応Static Web Appsを作成する際に、リージョン指定をしなくてはいけないのですが、こちらはAzure FunctionsにデプロイするAPIのみ、指定したリージョンにデプロイされるものなので、静的コンテンツのデプロイ先としてはどこのリージョンを指定しても良さそうです。ですので、どのリージョンを選択しようと、アクセスした地域の一番近いApp ServiceにTraffic Managerがルーティングしてくれる仕様となっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/60bc7a70-1c09-e2e3-9a66-011d3a9cbe5a.png)

具体的な裏側が気になる方は、こちらのブログ記事を読まれるとスッキリすると思います。

[App Service Static Web Apps の仕組みを探る（非公式）](https://blog.shibayan.jp/entry/20200521/1590056371)

##Static Web Apps作成する際、自動的にビルド＆デプロイの手順が書かれたymlファイルを定義してくれる
最初の説明にもありましたが、Static Web Appsはビルド環境としてGitHub Actionsが強制的に使われるように設定されているため、コンテンツを更新する度にビルドを走らせるJAMstack運用も可能となっています。以下が簡単な手順です。

Static Web Appsを作成する際に、GitHub アカウントと連携するよう聞いてきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/79ce4e60-51cc-002b-d67c-1fec9b42932b.png)

認証が完了すると、どの組織、リポジトリ、ブランチとSyncするか聞いてくるので、予めPushしておいたGitHubのリポジトリとブランチを選択します。ただこれで「確認および作成」ではなくて、必ず「次:ビルド >」を選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/10ee1d6e-cd32-1775-ff55-5303eeace42e.png)

ビルドの設定の中では、「アプリの成果物の場所」を設定します。こちらにはデプロイすべきファイル群が格納されるディレクトリを設定します。今回はTypeScript、ReactでHTML/JSファイルをビルドする場合は、buildといったディレクトリにビルド結果のファイル群を格納しますので、そのディレクトリ名を指定しておきます。リポジトリのルートディレクトリにindex.htmlファイルなどを格納している場合は、この項目は空のままで構いません。「アプリの成果物の場所」が設定できると「確認および作成」を押して、Static Web Appsを実際に作成していきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/810d8187-d982-7cd1-d255-997527f9ddb2.png)

Static Web Apps自体は1～2分で完成しますが、同時にGitHub Actionsとの連携もされ、自動的にビルド＆デプロイが実行されます（こちらは5分ぐらいで完了します）。GitHubアカウントを見れば、Actionsというタブが増えているのが分かると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/032dd3ba-19da-aee9-9145-9a3b46329bbe.png)

またymlファイルも自動的に生成されていることも分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/15448ca1-1b22-1ea9-52a0-ad0224e66e23.png)

ビルド＆デプロイが完了したら、あとはStatic Web Appsのリソースからサイトを閲覧しにいくだけです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/18687272-922c-cfd1-29b1-5888cd6a9f24.png)

無事見れました！これでコンテンツを更新する度にビルドを走らせるJAMstack運用の完成となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/fc204aed-e8fe-49a1-f5ce-6ce75a3af415.png)

##Static Web Appsのルーティング定義は *routes.json* で記述すれば問題なし
今回、若干引っかかったのがこのルーティングの定義。実はAzureのサービスの中に、Static Web Appsと同じように静的コンテンツを配信できるBlob StorageのStatic website hostingというサービスが存在しています。静的コンテンツを配信するという観点では同じようなことができるのですが、Static Web Appsと同じように細かいルーティング設定ができません。「じゃあStatic Web Appsはどうやってルーティング定義するんだろう？」と疑問に思ったのですが、さすが新サービス、*routes.json* で記述してあげれば何の問題なく動くことが分かりました。

[Static Web Appsのルーティングのドキュメントはこちら](https://docs.microsoft.com/ja-jp/azure/static-web-apps/routes)

Reactの場合は *public* フォルダー内にroutes.jsonを配置して、ビルド＆デプロイすれば自動的に読み取ってルーティングをしてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350899/13b5bdbf-3531-5cba-cbb9-593174096fac.png)

これで、*index.html* 以外のPathでアクセスしたときも404のNot Foundにならなくて済みます。

#まとめ
まだPreviewですが、このクオリティのものを**無料**で使えるのはやはり助かります。またGAされたとしても、Blob Storageより少し高くて、App Serviceより安い価格が期待できると思うので、今回の私のようにSPAを構築しようとしている方にとってはStatic Web Appsを選択肢のひとつに入れてもいいのではないかなと思います。

一度触ってみたいと思う方は、Microsoftが無償で提供している学習ポータルのMS Learnがあるのでそちらから試してみると良いと思います。
[Azure Static Web Apps で Angular、React、Svelte、または Vue の JavaScript アプリと API を発行する](https://docs.microsoft.com/ja-jp/learn/modules/publish-app-service-static-web-app-api/)