はじめに
こちらは慶應義塾大学理工学部のアドベントカレンダー23日目の記事です。
Azure Static Web AppsやAzure Functionsの名前は前から知ってるし、便利なのも知ってるけどお金結構かかりそうだな、という偏見もあり中々使う機会がありませんでしたが、仕事で使う必要が出てきたので色々と調べていたところ、簡単なアプリなら無料で作れることがわかりました。そこで自分の勉強のためにも、今回は静的なWebアプリを構築できるAzure Static Web AppsとAzure Functionsを利用して、動的Webサンプルアプリのサンプルとしてオリジナル個人ブログを作ってみようと思います。
Azure Static Web Appsとは
Azure Static Web Appsとは静的なWebアプリをホスティングするサービスです。後で紹介するAzure Functionsと組み合わせることで、簡単な動的Webアプリを作ることができます。
静的Webアプリとは既に作成されているページを表示するWebアプリのことを指し、動的Webアプリとはアクセスごとにページを作成して表示するWebアプリのことを言います。
似たようなサービスで、App Serviceというものがありますが、こちらはサーバランタイムが必要な動的なWebアプリを作成したい場合に向いていています。しかし、本記事のように簡単な動的WebアプリであればAzure Static Web Apps × Azure Functionsでも構築することが可能です。
Azure Static Web Appsの料金
2022年12月現在のAzure Static Web Appsの料金です(1 USD = 138.795 JPY)。今回のように簡単なアプリであればFreeプランで利用することができます。

Azure Functionsとは
Azure Functionsとはサーバーレスで定義済みの関数を実行することができるソリューションです。Azure Functionsの関数はC#、Java、JavaScript、PowerShell、Pythonのいずれかを使って記述することができます。
サーバーレスとはファイルのアップロード、データベースの変更、スケジューリングによる実行などイベントが発生したときだけ処理を実行する仕組みであり、通常のサーバーのように常に稼働させていく必要はなく、必要な時のみ利用することができるためサーバー代のコストカットを期待できます。
Azure Functionsの料金
こちらの表は2022年12月現在のAzure Functionsの料金です(1 USD = 138.795 JPY)。

表によると、Freeプランでも1か月あたり40 万GB秒の実行時間と100 万回の実行を行うことができます。100 万回という実行回数は、30 秒に1 回の頻度で1か月処理を実行し続けることが可能なため、今回のサンプルアプリでは十分な実行回数になります。
GB秒の単位の意味は、関数が実行される秒と消費メモリ量を掛け合わせた単位です。例えば、1 回の実行に1 秒と1 GBのメモリが必要な関数を1 回実行したとすると、その関数によるサーバーの使用時間は1 GB秒になります。
動的Webアプリの作成フロー
今回のWebアプリは次のような流れで作成します。
1. VSCode拡張機能のインストール
Webアプリを作成する下準備として、まずはVSCodeの拡張機能を2つインストールしましょう。
①Azure Static Web Apps
左にあるアクティビティバーから拡張機能のロゴを選択し、Azure Static Web Appsと入力すると、次の画像のような拡張機能が見つかるのでインストールしてください。

②Azure Functions
また、同様にしてAzure Functionsの拡張機能もインストールしておきましょう。

2. GitHubリポジトリの作成
次にリモートリポジトリを作りましょう。今回はリポジトリ名をSampleAzureStaticWebAppsとしました。リポジトリ名を入力した後、Create repositoryのボタンを押せば作成完了です。

リポジトリを作成した後、次のような画面が表示されるので、creating a new fileを押して次のようなindex.htmlファイルをコミットしましょう。

hello world
最後に、index.htmlをローカルにクローンして下準備完了です。
C:\Users\yus\SampleApp> git init
C:\Users\yus\SampleApp> git clone https://github.com/yus04/SampleAzureStaticWebApps.git
3. Webページの公開
次にAzure Static Web Appsを使って、先ほど作成したindex.htmlを表示するWebページを公開しましょう。Ctrl + Pでコマンドパレットを開いた後、>create Static Web Appと入力して表示された>Azure Static Web Apps: Create Static Web App...を実行します。

すると、Azureにサインインするように求められるのでSign in to Azure...を選びます。(アカウントを持っていない場合はCreate an Azure Account...を選択します。)

次にサブスクリプションを聞かれるので、使うサブスクリプションを選びます。

アプリの名前を聞かれるので、自分で決めたアプリの名前を入力します。

Azure Functionsのリージョンを選びます。私はEast Asiaを選びました。

使いたいフレームワークを選びます。私はReactを選択しましたが、何を選んでも大丈夫です。

アプリの場所を決めます。デフォルトのままでよいです。

ビルドファイルの場所を決めます。こちらもデフォルトのままでよいです。

無事にアプリの作成を完了したら、アクティビティバーからAzureのロゴを選択し、表示されたファイルツリーの中からStatic Web Appsをクリックします。展開されたフォルダの中に先ほど作成したアプリ(この画像の場合ではSampleAzureStaticWebApps)を右クリックし、Browse Siteを押します。

index.htmlの中身が表示されれば静的Webページの出来上がりです。

4. APIの作成と連携
ここまでのところで、hello worldを表示する静的Webページができました。なので、最後にAzure Functionsを使って動的アプリにしましょう。Ctrl + Pでコマンドパレットを開き、>create Http Functionと入力して表示されたAzure Static Web Apps: Create HTTP Function...を実行します。

するとAPIで使うプログラミング言語を聞かれます。ここではJavaScriptを選択します。

APIの名前を聞かれます。今回はデフォルトの関数名を使います。

そうすると以下のように、先ほど選択した言語で関数を作ってくれます。

ここで、index.htmlとindex.jsを次のように書き換えます。
<b id="res">...</b>
<script>
(async function() {
const { time } = await( await fetch(`/api/HttpTrigger1`)).json();
document.querySelector('#res').textContent = time;
}());
</script>
module.exports = async function (context) {
context.res.json({
time: get_time()
});
};
function get_time(){
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth()+1;
var date = now.getDate();
var hour = now.getHours();
var minute = now.getMinutes();
return (
year + "/" +
month + "/" +
date + " " +
hour + ":" +
minute
);
}
contextとは、エクスポートされる関数の最初の引数です。バインディングデータの送受信、ログ記録、ランタイムとの通信に使用に使用されます。
変更をpushします。
C:\Users\yus\SampleApp> git add .
C:\Users\yus\SampleApp> git commit -m ""
C:\Users\yus\SampleApp> git push origin master
再び、アプリをブラウジングしてグリニッジ標準時(GMT)が表示されればAzure Functionsが無事に機能していることを確認できます。

おわりに
今回はAzure Static Web AppsとAzure Functionsを使って簡単な動的Webアプリを作ることができました。Webアプリを公開する際に面倒なビルドやデプロイはGitHub Actionsを使って自動化されているため、快適に開発することができました。ポートフォリオや簡単なコーポレートサイトであれば、今回のやり方でも十分に作れると思いました。
