動機
これまで個人のウェブサイトをGitHub Pages上でJekyllを使って公開していました。
ただ幾つか制約に感じることがありました。
- Jekyllプラグインのうち一部しか使うことが出来ない
- pull requestを送ってもプレビューが見れない
- サーバーサイドで何か処理をしたくなった場合、別途自前で用意しなければならない
1つ目は、書いてあるそのままで、GitHub Pages上で使えるJekyllのプラグインはセキュリティの問題から下記のURLに記載されているものに限定されています。
以前からlinkpreviewというプラグインを使いたいと思っているのですが、この制約のためGitHub Pages上では利用できないでいました。
2つ目は、修正したページやスクリプトなどを試す際には実際に本番環境としてデプロイするしか方法が無いということです。
NetlifyやVercelなどのように、pull requestのブランチごとに別ドメインとしてデプロイしてくれるような仕組みがあると便利です。
3つ目は、応募フォームやちょっとしたデータを受け取る、もしくはデータを取得するためのAPIのようなものが欲しい場合を指しています。
そういった時は、応募フォームであればSaaSのサービスを利用することで満たせる場合もありますが、カスタマイズが難しい場合もありますし、個別の要件を満たせない場合もありえます。
NetlifyやVercelであればそういったAPIサービスを構築する機能が既にあります。それらを利用すれば良いのですが、無料だと利用制限があったりします。
そこでAzure Static Web Appsですよ
そうこう考えている中で、Azure Static Web Appsに自分は行き着きました。
その経緯について書きます。
前述の制約のうち1つ目は移行すればすぐに解決です。
2つ目の制約は、Azure Static Web Apps自体がそもそも機能として提供しています。
これも即時解決です。
3つ目についても、APIをAzure Functionsの仕組みをそのまま利用して開発できる機能を持っているのでそれを利用すれば解決です。
NetlifyにもFunctionsというAWS Lambdaを利用した仕組みが用意されています。AWS Lambdaに慣れているようであればそちらも十分な選択肢かと思います。ここは個人的にAzure Functionsの方が使い慣れているという点で選んでいます。また、同じAzureサブスクリプション上ですでに作成した他のAzureのリソースとの連携ができ、当然のことながら他のAzureリソースと同じようにAzure Static Web Appsも扱えるので管理が楽になったと感じています。課金もAzureのサブスクリプションにまとめられる1のも利点であると考えています。
といった制約が乗り越えられたので、Azure Static Web Appsへの移行を決めました。
引っ越す
これは非常に簡単です。下記のドキュメントにある手順通りで、
既にGitHub Pagesのリポジトリは持っていたので、この手順の前半は省略できました。
カスタムドメインの切り替えなど、別途行いましたが、利用しているDNSのCNAMEレコードを更新すれば完了です2。
以上。これだけ。
ローカルでの開発環境を作る
Static Web Appsをローカルの環境で再現するためのCLIがあるので、それを利用してデプロイ前に動作を確認できるようにします。
まずはCLIをインストールします。
$ cd /path/to/your/jekyll-site
$ npm init --yes
$ npm install -D @azure/static-web-apps-cli
インストールしたパッケージをGitの管理に混ぜないように.gitignore
を更新します。
node_modules/
同様に、Jekyllがビルドの対象にしないように、_config.yml
にexclude
オプションを追加します。
exclude:
- api/
- node_modules/
- Gemfile*
- package*.json
exclude
オプションを指定すると、それまでデフォルトで除外していたようなGemfile
なども指定する必要があるようです。
それでは起動してみます。
$ npx swa start http://localhost:4000 --run 'bundle exec jekyll serve'
これによって、
-
--run
オプションんにより、Jekyllの開発用のWebサーバー(デフォルトでhttp://localhost:4000
)が起動 -
start http://localhost:4000
で、立ち上がった開発サーバーにプロキシとして接続
ということを指定しています。
また別の方法として、swa自体がウェブサーバーとしても利用できるので、Jekyllはビルドのみしてもらうことも出来ます。
$ npx swa start _site --run 'bundle exec jekyll build -w'
jekyll build
につけた-w
オプションは、ファイルの変更を監視(watch
)を指定しています。これにより、ファイルが追加されたり変更されるとビルドが自動的に実行されます。
これでローカルで確認できるようになったので、ブラウザでhttp://localhost:4280/
にアクセスすると、Jekyllでビルドしたコンテンツが参照できるようになっているはずです。
また、例えば404の応答を独自のHTMLに変更した場合の確認などができるようになります。
APIを作ってみる
APIを試すために、問合せフォームを作ってみました。実際にやってみたのがこちらのpull requestです。
以下、そのためにやった手順を書きます。
まず、Visual Studio CodeのAzure Static Web Appsという拡張をインストールします。
この拡張は、Azure上のAzure Static Web Appsリソースを操作したり、APIのためのFunctionを生成したりできます。
インストールできたら、実際にAPIのためのFunctionを生成します。
コマンドパレット(MacであればCmd+Shift+P
)を開き、Azure Static Web Apps: Create HTTP Function...
を選択し、Function名を入力し、好きなプログラミング言語を選択して、雛形を生成します。
例えば、JavaScriptでPostInquiry
という名前を指定したら、api/PostInquiry
というディレクトリが生成され、そのディレクトリの中に、function.json
やindex.js
というファイルが生成されます。
これは完全にAzure Functionsと同じです。しかしながら1つ大きな制限があり、Azure Static Web AppsのAPIではHTTPトリガーしか使えないという点です。
この制限が厳しい場合は、別途Azure Functionsリソースを生成して、それをAzure Static Web Appsで利用するという方法があるようです(未確認)。
このAPIをローカルで起動できるようにするための環境を作っていきます。これもまたAzure Functionsをローカルで開発するときと全く同じ手順です。
$ npm install -g azure-functions-core-tools@3
もしくは、Macを利用している人であればHomebrewでもインストールできます。
$ brew install azure/functions/azure-functions-core-tools@3
これで起動するための準備ができたので、swa
コマンドを使って起動する。
$ npx swa start _site --run 'bundle exec jekyll build -w' --api ./api
先に実行した際のコマンドに--api
オプションが追加されている。このオプションにより、APIがどのディレクトリにあるのかを指定しています。
ここで起動できなかった場合、原因の1つとしてサポートされているNode.jsのバージョンではない可能性があります。
Azure Functionsではv14系がサポートされているバージョンで最も最新のものです(2021/8/25時点)。
例えば、v16系がインストールされている環境でswa
コマンドで起動しようとすると、下記のようなエラーがログに出てきます。
[api] Azure Functions Core Tools
[api] Core Tools Version: 3.0.3477 Commit hash: 5fbb9a76fc00e4168f2cc90d6ff0afe5373afc6d (64-bit)
[api] Function Runtime Version: 3.0.15584.0
[api]
[swa] - Waiting for http://localhost:7071 to be ready
[api] [2021-08-25T08:07:49.409Z] Cannot create directory for shared memory usage: /dev/shm/AzureFunctions
[api] [2021-08-25T08:07:49.409Z] System.IO.FileSystem: Access to the path '/dev/shm/AzureFunctions' is denied. Operation not permitted.
[run] Configuration file: /Users/satoutatsuya/Projects/private/satoryu.com/_config.yml
[run] Remote Theme: Using theme mmistakes/minimal-mistakes
[api] [2021-08-25T08:07:50.426Z] /usr/local/Cellar/azure-functions-core-tools@3/3.0.3477/workers/node/dist/src/nodejsWorker.js:35
[api] [2021-08-25T08:07:50.426Z] throw message;
[api] [2021-08-25T08:07:50.426Z] ^
[api] [2021-08-25T08:07:50.426Z] Incompatible Node.js version (v16.7.0). Refer to our documentation to see the Node.js versions supported by each version of Azure Functions: https://aka.ms/functions-node-versions
[api] [2021-08-25T08:07:50.426Z] (Use `node --trace-uncaught ...` to show where the exception was thrown)
起動できた場合、ブラウザでhttp://localhost:4280/api/PostInquiry
にブラウザからアクセスしてみると何かしらレスポンスがあるはずです。
あとは実際にAPIを実装します。
APIのコードを実装し、保存すると、そのタイミングでAPI(Azure Functions Core Toolsで起動されたプロセス)が再起動されます。
いざデプロイ
デプロイした際のビルドは、npm run-script build
またはnpm run-script build:azure
で行われます。
どうやらpackage.json
が追加されるとnode
のアプリケーションとして判断されるようで、package.json
内にscripts.build
またはscripts.build:azure
が定義されている必要があります。
またGitHub Actionsのビルドの設定ファイル.github/workflows/azure-static-web-apps-nice-field-0cd594e00.yml
(拡張子手前のランダムな文字列はアプリケーションによって異なります)の中にあるapi_location
でAPIのコードがあるディレクトリを指定します。
api_location: "./api"
ここまで出来たらgit commmit
でコミットを作成し、そのブランチをgit push
でGitHub上に上げましょう。
master
ブランチであれば、そのままGitHub Actionsが実行されて、ビルドとデプロイが実行されます。
もし作業用のブランチにコミットしたのであればpull requestを作成すると、実稼働前環境へデプロイされます。
実稼働前環境は、別ドメインでなおかつ環境変数は本番環境と同じものが使用できます。DBなどを共用してしまうと本番環境に影響が出てしまう可能性があるので、多少注意が必要です。
おわりに
ということで、今回実施したJekyllで生成したサイトをGitHub PagesからAzure Static Web Appsへ引っ越しして、問合せフォームをAPI(Azure Functions)で作ったことについて書きました。
Netlifyなど他の静的コンテンツを配信するサービスのように使いやすく、GitHub Actionsでビルドとデプロイができるので既存の仕組みの組み合わせのため学習コストが低いように思いました3。
個人のウェブサイトのようなものであれば、無料プランでも十分使えるものだと思います。
今回はまだ手を付けていませんが、APIから他のAzureのサービスと連携させることもできるでしょう。
例えば、問合せを受けたらAzure Queue Storageへキューイングし、それをトリガーにLogic AppsでExcelに問合せ内容を記録するといったこともできると思います。
それらの連携が扱いやすそうなのもAzure Static Web Appsの良いところだと思います。
ということで、Azureのアカウントを持っていて、個人のウェブサイトを作ろうとするのであれば、Azure Static Web Appsは十分な選択肢だと思いました。