Azure Static Web AppsでNuxt.jsアプリを作成する

# 本記事について
本記事では Azure Static Web Apps の紹介と
実際に Nuxt.js を用いて静的サイトを構築した際のメモを記載します。

誤りがあればコメント等で教えていただけると大変嬉しいです。

# Azure Static Web Appsとは
**Azure Static Web Apps** とは、
その名の通りAzureの静的サイトホスティングサービスです。
さらに、大きな特徴として、Azure Functionsを内包しています。

つまり、
**SPA（シングルページアプリケーション）をまるっとホスティングしてくれるサービス**になります。
あとはデータベースさえ用意すれば、少なくともアプリケーションレイヤーでは必要十分なサイトが出来上がります。

なお、**デプロイにはAzure DevOpsまたはGitHub上のリポジトリ上でソース管理する必要があります**。

個人／お試し用環境は **無料** です！

## 余談：Azure Static Web Apps登場以前
Azure Static Web Appsは、2021年5月に満を持してリリースされました。
それ以前は、Azureで静的サイトをホスティングするには、
「Azure Storage」「Azure Web Apps」を使う必要がありました。
Azure Storageはストレージサービスであり、その中の一機能として静的サイトホスティングがありました。（AWSでいうS3ですね）
Azure Web AppsはWebアプリケーションホスティングのサービスなので、静的サイトホスティングとはまた少し違う形です。

静的サイトをホスティングする専用のサービスとなったことで、
React, Vue, Gatsbyなど様々なシングルページアプリケーションをデプロイしやすくなりました。


# Azure Static Web Appsの使い方
基本的にはMicrosoft Docsに説明や手順が書かれているので迷う点は少ないと思います。

https://docs.microsoft.com/ja-jp/azure/static-web-apps/

ただページ数がそこそこあったり、自身の開発環境によって色んなページを行き来する必要があります。
私の場合、**VScode × Azure DevOps × Nuxt.js**で、静的サイトを構築しました。
以降、私が実施した手順を以下に残します。


## ざっくり手順
1. Azure Devops 上にリポジトリを作成する。
1. VScode 上で Nuxt.js アプリケーションを作成する。    
1. Azure Portal から Static Web Apps のサービスを作成する。
1. Azure DevOps 上でパイプラインを作成する。
1. リポジトリにコードプッシュする
1. Static Web Apps にデプロイされ、サイトが出来上がる。


項2の Nuxt.js アプリケーションでは
*nuxt.config.json* および *package.json* は以下のように書き換える。

```nuxt.config.json
{
  "ssr": true,
  "target": "static",
}
```


```package.json
"scripts": {
  "dev": "nuxt dev",
  "build": "nuxt generate",
}
```

https://docs.microsoft.com/ja-jp/azure/static-web-apps/deploy-nuxtjs#generate-a-static-website-from-nuxtjs-build

※原因をつかめていませんが、*nuxt.config.json* で *ssr:false* の際に、後述するルーティング設定がうまく効かない状況になりました。

ここまで実施することで、Nuxtアプリケーションのデプロイまで実施することができました。


# Azure Static Web Appsの設定ファイル
Azure Static Web Appsの動作に関する設定ファイルは、*staticwebapp.config.json* というファイルに記載します。
（以降、*staticwebapp.config.json*を、設定ファイル と記載します）
なお、GA前は *router.json* という名前でしたが、現在は非推奨です。

設定ファイルでは、ルーティングや認証／承認機能を定義することができます。

https://docs.microsoft.com/ja-jp/azure/static-web-apps/configuration

nuxt.jsアプリケーションの場合、***static*フォルダの直下にこのファイルを新規作成**し、各種設定を記載してください。
これを行うことで、通常であればnuxt generate時にルートフォルダに設定ファイルが置かれるようになります。


## ルーティング設定
ルーティング設定は、URLアクセスした際にどうユーザーにページを表示するかを設定することができます。
以下は例です。

1. */oldpage* にアクセスされたら、ユーザーへ */newpage* を表示する。
2. 存在しないURLにアクセスされたら、 */custom404* を表示する。
3. 認証前に */mypage* にアクセスされたら、ユーザーへ */login* を表示する。

上記のような設定を簡単に行うことが出来ます。

## 認証設定
Azure Static Web Appsは、認証プロバイダとして、*AzureAD*, *GitHub*, *Twitter*を設定することが可能です。
これら認証プロバイダを利用することで、作成した静的アプリケーションに簡単に認証機能をつけることが可能です。
なお、上記の認証プロバイダ以外にカスタム認証プロバイダ（auth0等）も設定することが可能なようです。
（その際は、有償プラン必須になります）

https://docs.microsoft.com/ja-jp/azure/static-web-apps/authentication-authorization

認証せずにサイトを利用しているユーザーは、ロール *anonymous* となります。
認証プロバイダを通しサイトを利用しているユーザーは、ロール *authenticated* となります。

たとえば、前述した
「認証前に */mypage* にアクセスされたら、ユーザーへ */login* を表示する」
を実現したい場合は、以下のようにルーティング設定を記載することで、認証されたユーザー以外には/mypageを利用させないことができます。

```staticwebapp.config.json
{
  "routes": [
    {
      "route": "/mypage",
      "allowedRoles": ["authenticated"]
    },
}
```


ただ、この２つロールだけですと、認証したかしていないかの違いしかなく、
もう少し細かい制御をしたくなるかもしれません。たとえば、
GitHubでログイン可能なユーザーuser1とuser2がいた場合、
user1にはサイトを利用したいが、user2にはサイトを利用させたくない場合です。

この場合、Azure Portal上で事前にロールの定義を行い、ユーザーをそのロールに招待する必要があります。

https://docs.microsoft.com/ja-jp/azure/static-web-apps/authentication-authorization#add-a-user-to-a-role

上記手順に従い、ロールを作成します。
その後、設定ファイル上のルーティング設定で、たとえば以下のようにします、

```staticwebapp.config.json
{
  "routes": [
    {
      "route": "/login",
      "allowedRoles": ["anonymous"]
    },
    {
      "route": "/sitemain",
      "allowedRoles": ["作成したロール名"]
    },
}
```

こう記載することで、/sitemainページにはそのロールを保持したユーザーしかアクセスできないようになります。


## Azure Functionsの実装

 ~~Azure Functionsを内包させるには、apiロケーションを作成する必要があります。~~
~~https://docs.microsoft.com/ja-jp/azure/static-web-apps/publish-devops~~
~~上記手順に従う場合、
app_locationは/
api_locationは/api
としていました。
つまりnuxt.jsの場合は、nuxt generateによって出力されるフォルダ=「dist」が/相当になります。
dist配下にはstaticのコンテンツが配備されています。
したがって、staticフォルダ直下にapiフォルダを作成し、その中にAzure Functionsを定義していけばよいです。~~


どうやら私が以下のページを見落としていたようでした。

https://docs.microsoft.com/ja-jp/azure/static-web-apps/add-api?tabs=vue
こちらに手順が記載されていました。
プロジェクトルートにapiフォルダが作成されるようですので、
これをstaticに移すか、nuxt build時にapiフォルダをルートに配備する必要がありそうです。


# おわりに

この1年、お仕事でAWS上のNuxt.jsアプリケーションに携わらせていただいていました。
（といってもAWSアーキテクチャ部分ではなくコーダーとしてが主ですが、、、）
AWSで行っているものをAzureだとどうなるんだろう？という興味本位からAzure Static Web Appsを利用してみました。

個人利用では無償ですし、
本記事では紹介していませんが、AzureのNoSQLDBである *Cosmos DB*も実はある程度無償で利用可能なので
ちょっとした開発や勉強にちょうど良い環境です。

ネット上ではまだまだAzure Static Web Appsの情報は乏しいのですが、
Microsoft Docsが比較的充実していることや、
VueやReactのフロンドエンドの代表格 × APIという今では当たり前な構成のアプリケーションを
ワンサービスのみでデプロイすることができるのがサービスの強みだなと思いました。