Azure Static Web AppsでサーバーレスSPAアプリを作ってみた

2021年9月9日

はじめに

この記事では、ファイル管理アプリの作成を題材に、Azure Static Web Appsを使ったサーバーレスのSPA(シングルページアプリケーション)を開発する方法をご紹介します。工程を大きく4つの手順とページに分けて、下記の手順で開発していきます。

手順

  1. プロジェクト・Azureリソースの作成とインストール作業 ←このページでやること
  2. 認証機能の実装
  3. ストレージの作成とAPIの実装
  4. フロントエンドアプリの実装と動作確認

作成するアプリの完成形

完成形のアプリはこちら↓になります。

作成したソースコードはこちらのリポジトリで公開しており、リソースの作成と環境変数を設定をすることで、同様のアプリを動かすことができます。その際の手順についてはREADMEを参照してください。

構成

  • Azureサービス
    • Azure Static Web Apps
    • Azure Data Lake Storage Gen2 (階層型名前空間あり、冗長性オプションLRS)
  • フロントエンドアプリ
    • Create React App (TypeScript + npm)
    • Material UI
  • API
    • Node.js (TypeScript + npm)

開発言語をTypeScriptで統一することで、Azure Static Web Appsの特徴の1つである、単一プロジェクトでフロントエンドとAPIのソースコードを管理できる利点を活かすことができます。

前提条件

あらかじめ、Azureアカウントとサブスクリプション作成しているものとします。また、リソースの作成の際にVisual Studio Codeの拡張機能を利用するため、エディタはVisual Studio Codeを使用します。

料金については、Azure Static Web AppsはFreeプランを利用するため無料ですが、ストレージは使用量に応じた料金が発生しますので要注意です(12ヶ月無料期間なら無料)。

仕様

  • Azure Active Directory・GitHub・Googleのプロバイダーでサインインできる
  • Twitter・Facebookで認証しようとした際は404ページを表示する
  • サインインしたユーザーはファイルを一覧表示、ダウンロード、削除、アップロードできる
  • ストレージの認証は共有キーを使用する

下準備

開発を始めるに当たり、まずはプロジェクトの作成や、Azureリソースの作成、開発に必要なCLIや拡張機能をインストールします。

① Visual Studio Codeの拡張機能をインストール

ローカル環境でAzureのリソースを作成するために、下記2つの拡張機能が必要になります。

  • Azure Static Web Apps
  • Azure Functions

Visual Studio Codeの拡張機能のタブでそれぞれazure functionsstatic webappsで検索して、拡張機能をインストールします。

② ローカル環境でアプリを実行するためのnpmパッケージのインストール

ローカル環境でアプリを実行する際に必要な2つのパッケージをインストールします。

  • static-web-apps-cli
    ローカル環境でユーザー認証や、ルーティングのエミュレート、フロントエンドアプリとAPIを同一ポートで実行するために利用します。
npm install -g @azure/static-web-apps-cli
npm install -g azure-functions-core-tools@3 --unsafe-perm true

③ Create React Appのプロジェクト作成

下記コマンドでプロジェクトを作成します。

npx create-react-app my-app --template typescript

Create React Appの詳細は公式サイトを参照してください。

④ Azure Static Web Appsの作成

F1キーを押してStatic Web Appsと入力して、

Azure Static Web Apps: Create Static Web App...(Advanced)

を選択します。

VSCode 作成コマンド

ココに注意

コマンドパレットの「Azure Static Web Apps: Create Static Web App..」や、サイドメニューのAzureのタブを開いてから'+'ボタンを押すことでも作成できますが、リージョンやリソースグループなどが自動で設定されてしまうため、(Acvanced)の方を選択することをオススメします。

Azure Static Web Apps作成画面

リソースグループ、アプリの名前など、リソース作成に関する設定に加え、Gitリポジトリも同時に作成されるのでこちらも設定を行います。

基本的に入力された設定のままで問題ありませんが、Azure Static Web Appsのプランと、プロジェクト構成はそれぞれ、Free、Reactを選択します。

  • Azure Static Web Appsプラン:Free
  • プロジェクト構成:React
  • その他:既定の値

作成が終わると自動的にGitHub Actionsのデプロイワークフローが作成され、変更が自動でリモートリポジトリに反映されます。そのため、ワークフローが実行され、自動で割り振られたURLでステージング環境にデプロイされます。デプロイされたアプリは右クリックメニューの「Browse site」から確認することができます。

デプロイしたサイトにアクセスして、Reactのロゴマークが表示されていればデプロイ完了です。また、Azureのポータルで先ほど作成したAzure Static Web Appsのリソースを選択して「環境」をクリックすると、先程デプロイしたアプリが追加されていることが確認できます。

porta上のリソース

⑤ APIの追加

作成したAzure Static Web AppsにAPIを追加します。apiフォルダをルート直下に作成し、先ほどと同様F1キーを押し、Azure Static Web Apps と入力し

Azure Static Web Apps: Create HTTP Function... 

を選択します。名前の入力を要求されますので任意の値を入力します。今回はAPIの名前をstorageとしました。

すると、入力した名前のフォルダがapi フォルダ下に作成されます。上記の作業終了時点でこちら↓のようなファイル構成になります。

動作確認

フロントエンドアプリとAPIでやりとりができることを確認するため、既存のコードを修正してAPIからのレスポンスを表示させてみます。APIにアクセスするために、HTTPクライアントのaxiosをインストールします。

npm i axios
import axios from "axios"
import { useState, useEffect } from "react"
function App() {
  const [data, setData] = useState("")
  useEffect(() => {
    (async function () {
      const res = await axios.get(`/api/storage`)
      setData(res.data);
    })();
  });
  return <div>{data}</div>
}
export default App
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
const storage: AzureFunction = async function (context: Context,req: HttpRequest): Promise<any> {
  context.res = {
    status: 200,
    body: "Hello World",
  };
};
export default storage

フロントエンドアプリとAPIのプロジェクトで、それぞれでnpm installでパッケージをインストールしておきます。また、先程APIのソースコードを変更したので、ビルドしてからstatic-web-apps-cliでアプリを実行します。

npm run build --prefix api
swa start http://localhost:3000 --run 'npm start' --api api

今回はReactを利用しているため、ポート番号に3000番を指定していますが、使用しているフレームワークごとにポート番号は異なります。

詳細についてはstatic-web-apps-cliのドキュメントを参照してください。

上記のスクリプトでフロントエンドアプリとAPIを同時に実行できますが、APIのプロジェクトのビルドはされないため、事前のビルドが必要です。
http://localhost:4280にアクセスしてHello Worldが表示されていれば成功です。

アプリ動作画面

次のページでは、認証処理を実装にとりかかっていきます。

次のページへ >