ども!年末年始を抜けてぬるっと仕事に復帰を始めている龍ちゃんです。年末年始は、今まで溜まっていた検証+お部屋を片付けていたので、意外と充実していました。去年は、GitHub AcitonsとDevContainerでの環境構築作成をしっかりやっていた時期かなと振り返り、またブログにまとめていきます。
今回の内容は、以下の二つになります。
- Azure Static Web Apps上でNext.jsの静的サイト配信を行う(GitHub Actionsを用いたデプロイ)
- ローカルの開発環境をDevContainerで作成する(SWA CLIを活用してローカルでプレビュー)
ローカル環境でStatic Web Apps(以降:SWA)の挙動を確認することができる、SWA CLIを開発環境にインストールします。今回のゴールとしては、SWA CLI動作確認とSWAへのNext.js静的サイトを公開になります。
SWA CLIとは
Azureさん公式のエミュレーターになります。SWAの挙動をローカルで再現してくれます。開発時に特にうれしい機能として以下の二つかなと思います。
- SWA上に構築済みの認証をモックで試すことができる
- APIエンドポイントへのプロキシ
SWA上に構築済みの認証をモックで試すことができる
SWAでは、コンフィグファイルに追記するだけで色々な認証プロバイダー(Google / X / Apple / etc…)から認証を受けることができます。SWA上で構築済みのサービスになるので、ローカルで認証を試すことができません。そこで、ダミーのモックで認証を通った状況を作ることができます。認証後の情報取得方法もローカルで動作確認できるので、非常に助かります。
APIエンドポイントへのプロキシ
SWAでは、Azure Function(Freeプランでも可)やWeb Apps(Standardプランのみ可)で作成したAPIを/api
ルートと接続することができます。こちらも、SWA上で構築済みのサービスなのでローカルの開発では、SWAのプロキシを再現する必要があります(まぁ無理よな)。SWA CLIを使うことで、そのあたりの挙動も模倣して提供してもらえます。
開発環境構築
環境構築の内容に入っていきます。前提条件としては、DockerとDocker Composeコマンドが使えれば大丈夫です。最終的なファイルとしては、こちらのリポジトリに上がっています。
ディレクトリ構成としては、以下のようになります。
.
├── .devcontainer
│ └── devcontainer.json # DevContainer環境設定
├── .dockerignore
├── .env # local用環境ファイル
├── .github
│ └── workflows
├── Dockerfile
├── docker-compose.yml
├── my-app # Next.jsアプリディレクトリ
└── swa-cli.config.json # SWA CLIコンフィグファイル
- Next.jsの環境づくり
- node_modulesをvolumeマウント化
- SWA CLIのセットアップ (SWA CLI Config)
- 静的サイト用対応( staticwebapp.config / Next.js config)
Next.jsの環境づくり
まずは、Next.jsの環境を作っていこうと思います。ここでは、Nodeの環境を作成してDevContainerでいきなりアクセスしてしまいます。三つのファイルを作成してください。
Dockerfile
ARG NODE_VER
FROM node:${NODE_VER}
RUN npm install -g npm@11.0.0
RUN npm install -g @azure/static-web-apps-cli
USER node
WORKDIR /home/node/app
docker-compose.yml
version: "3.7"
services:
next:
build:
args:
- NODE_VER=22.12.0
context: .
dockerfile: Dockerfile
tty: true
volumes:
- type: bind
source: ./
target: /home/node/app
.devcontainer/.devcontainer.json
{
"name": "procject-dev",
"dockerComposeFile": ["../docker-compose.yml"],
"service": "next",
"workspaceFolder": "/home/node/app",
"customizations": {
"vscode": {
"extensions": [],
"settings": {}
}
},
"remoteUser": "node",
}
DevContainer内に入ったら、Next.jsのプロジェクトを作成します。今回は、create-next-appから提案されるmy-appで話を進めていきます。ここは任意に変更してください。
npx create-next-app@latest
これで、Next.jsの環境が作成することができました。
node_modulesをvolumeマウント化
node_modulesをvolumeマウントにすることで、コンテナ内に収めてしまいます。こちらの対応をしておくことで、元ファイル側のサイズを小さくすることができます。また、bindマウントしないことによりビルド速度を上昇させることができます。
こちらでやっていることは、「.dockerignoreでビルド時にnode_modulesをなかったことにして、Dockerfileでnode_modulesを作成してビルド、dokcer-compose.ymlでnode_modulesをボリュームマウントする」となります。Dockerファイルで作成している理由としては、dokcer-compose.ymlファイル経由で作成させるとroot権限で作成されて涙を呑むからですね。
追加で、.dockerignore
ファイルを作成してください。
.dockerignore
my-app/node_modules
Dockerfile
ARG NODE_VER
FROM node:${NODE_VER}
RUN npm install -g npm@11.0.0
RUN npm install -g @azure/static-web-apps-cli
USER node
WORKDIR /home/node/app
RUN mkdir my-app
COPY --chown=node:node my-app my-app
WORKDIR /home/node/app/my-app
RUN mkdir node_modules
RUN chown node:node -R node_modules
RUN npm install
docker-compose.yml
version: "3.7"
services:
next:
build:
args:
- NODE_VER=22.12.0
context: .
dockerfile: Dockerfile
tty: true
volumes:
- type: bind
source: ./
target: /home/node/app
- type: volume
source: node_modules
target: /home/node/app/my-app/node_modules
volumes:
node_modules:
ファイルの適応が完了したら、**DevContainerを必ずRebuildしてください。**以上で、node_modulesのボリュームマウント化完了です。
Next.jsのアプリを作成した際に発生したnpm installで持ってきたnode_modulesが元ファイルに残っていると思います。気になる方は、コンテナから抜け出して、元ファイルのnode_modulesを削除してください。
SWA CLIのセットアップ
SWA CLI自体は、Dockerfileのnpm globalインストールですでに導入済みです。コンテナ内で以下のコマンドで確認してください。
swa --version
バージョン情報が返ってくれば、インストール自体は完了しています。また、以下のコマンドで対話的にコンフィグファイルを作成することができます。
swa init
フレームワーク等も自動で判断して作成してもらえるので非常に便利なコマンドです。
対話的に作成しなくても、以下のファイルをコピペしてもらえれば起動することができます。
swa-cli.config.json
{
"$schema": "<https://aka.ms/azure/static-web-apps-cli/schema>",
"configurations": {
"app": {
"appLocation": "my-app",
"run": "npm run dev",
"appDevserverUrl": "<http://localhost:3000>"
}
}
}
上記のファイルを作成したディレクトリで、以下のコマンド一つでエミュレーター起動までやってもらえます。
swa start
特に設定していなければ、http://localhost:4280で起動しているかと思います。
静的サイト用対応
最後に、Next.jsとSWAそれぞれで静的サイト用の設定を追加していきます。Next.jsのコンフィグファイルを編集して静的エクスポートを有効にします。
my-app/next-config.ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
output: "export",
trailingSlash: true,
};
export default nextConfig;
こちらの設定を有効にするだけで、npm run build
でout
ファイル内に静的ファイルが生成されます。trailingSlash: true
では、静的ファイルのエクスポート時にディレクトリ/index.html
という形式でファイルを読み込んでくれます。
次に、SWA側の設定ファイルです。こちらは、ローカル用と本番用の二つのファイルを用意します。ローカルでは、コンフィグファイルを指定して起動します。本番用のファイルはnpm run build
で静的ファイルにそのまま書き込まれるように、Next.jsのpublic
ディレクトリに作成します。今回は、Next.jsの設定に併せてtrailingSlash
の設定のみ追加します。
ローカル:.env/local/staticwebapp.config.json
本番用:my-app/public/staticwebapp.config.json
{
"trailingSlash": "auto"
}
最後に、SWA CLIのコンフィグファイルにローカルのstaticwebapp.config.json
の位置を教えます。
{
"$schema": "<https://aka.ms/azure/static-web-apps-cli/schema>",
"configurations": {
"app": {
"appLocation": "my-app",
"run": "npm run dev",
"appDevserverUrl": "<http://localhost:3000>",
"swaConfigLocation": ".env/local"
}
}
}
これでswa start
では、.env/local
内のコンフィグファイルが読み込まれて実行します。
SWA deploy with GitHub Actions
事前準備としては、Azure Static Web AppsのデプロイトークンをGitHubのSecretとして保存しておく必要があります。今回は、環境 deploy内にAZURE_TOKEN
として保存しているとして進めていきます。開発環境はDockerで作成しましたが、デプロイ自体はActions内でビルドしてデプロイをしています。
on:
push:
branches: ["main"]
workflow_dispatch:
env:
NODE_VERSION: "22.x"
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: my-app/package-lock.json
- name: npm install, build, and test
run: |
npm install
npm run build
working-directory: my-app
- name: Upload Cache app
uses: actions/cache/save@v4
with:
path: my-app/out/
key: ${{ runner.os }}-app-${{ github.sha }}
deploy:
runs-on: ubuntu-24.04
needs: build
environment: deploy
steps:
- uses: actions/checkout@v4
- name: Download Cache app
uses: actions/cache/restore@v4
with:
path: my-app/out/
key: ${{ runner.os }}-app-${{ github.sha }}
- name: Build And Deploy
uses: Azure/static-web-apps-deploy@1a947af9992250f3bc2e68ad0754c0b0c11566c9
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
output_location: "my-app/out/"
app_location: "my-app/out/"
skip_app_build: true
内容としてはシンプルで、以下の順序で実行されます。
- ビルド
- アプリケーションのビルド
- 静的ファイルoutをキャッシュ
- デプロイ
- キャッシュからアプリを復元
- 静的ファイルをSWAに配信
Azure/static-web-apps-deploy
はビルドもアクションの中で実行してくれる優れものです。ですが、今回はCI上でビルドを実行して、デプロイのためだけに使用しています。
終わり
今回の開発環境構築で特に詰まった点としては、Next.jsで静的ファイルを配信するための設定周りですね。Next.jsとSWAでそれぞれ設定が必要な点は盲点でした。
最近は、フロントエンドの開発環境構築はCI/CDパイプラインを組むところまでやるべきなのかもしれないと思ってきましたね。次回は、バックエンドの環境構築について記載を進めておきます。Azure上で公開するための開発環境構築なんて必要そうですね。三日間ぐらいDockerと戯れすぎて、yamlファイルアレルギーになりそうです。
では2025年もよろしくお願いします。これは1月中に毎回言っておきます。