はじめに
ども!先輩社員から Azure Static Web Apps のビルドの相談を受けて、そういえばそのブログを書いたことないなって「はっ!」となった龍ちゃんです。
今まで、過去にセットアップしたものを使いまわしていたんですけど、身近にありすぎて忘れていました。そんなわけでまとめていきます。Azure Static Web Apps はよく使用します。今回の記事をふんだんに使ったブログは「Azure Static Web Apps: x-ms-client-principal で安全なロールベース制御」です。
それでは本題に入ります。Azure Static Web Apps(以下、SWA)を使っていて、「デプロイに時間がかかるな…」と感じたことはありませんか?
Azure Portal から SWA を作成すると、GitHub Actions のワークフローファイルが自動生成されます。このデフォルト設定では、Microsoft の Oryx ビルドシステムが使用され、プロジェクトを自動的に検出してビルドしてくれます。
しかし、このデフォルト設定には以下のような課題があります:
- ❌ 毎回依存関係のフルインストールが発生(キャッシュなし)
- ❌ テストや Linter の実行ができない
- ❌ ビルドプロセスのカスタマイズが困難
本記事では、GitHub Actions 上でカスタムビルドを実装し、デプロイ時間を短縮する方法を解説します。
Oryx ビルドシステムとは
Oryx の概要
Oryx(オリックス)は、Microsoft が開発したオープンソースのビルドシステムで、ソースコードを自動的に実行可能なアーティファクトにコンパイルします。
公式リポジトリ: https://github.com/microsoft/Oryx
Azure Static Web Apps、Azure App Service、Azure Functions などで利用されています。
自動検出の仕組み
Oryx は以下のように動作します:
- リポジトリの内容を分析
- 使用されているプログラミング言語・フレームワークを検出
- 適切なビルドコマンドを自動実行
具体例(Node.js の場合)
検出内容 → 実行されるコマンド
----------------------------------------------------
package.json が存在 → npm install
→ npm run build または npm run build:azureデフォルトワークフローの動作
Azure Portal から SWA を作成すると、以下のようなワークフローファイルが自動生成されます:
name: Azure Static Web Apps CI/CD
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main
jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v3
with:
submodules: true
lfs: false
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
action: "upload"
app_location: "/" # アプリのソースコードパス
api_location: "" # APIのソースコードパス(オプション)
output_location: "dist" # ビルド済みアプリのディレクトリ(オプション)このワークフローの特徴:
- ✅ シンプルで設定が簡単
- ✅ Oryx が自動的にビルド設定を検出
- ❌ 毎回依存関係のインストールが発生(キャッシュなし)
- ❌ ビルド時間が長い
- ❌ テストの実行ができない
- ❌ ビルドプロセスのカスタマイズが困難
カスタムビルドで得られるメリット
GitHub Actions 上でビルドを実行することで、以下のようなメリットが得られます。
1. 依存関係のキャッシュ
actions/setup-node@v6 の組み込みキャッシュ機能を使用することで、依存関係のダウンロード時間を大幅に短縮できます。
- uses: actions/setup-node@v6
with:
node-version: "20"
cache: "npm" # npm, yarn, pnpm をサポート
cache-dependency-path: "package-lock.json"2025 年 11 月時点の推奨バージョン: actions/setup-node@v6 が最新版です。v6 では Node.js 24 ランタイムへのアップグレードやセキュリティ強化が行われています。v6 でも v4 と同様に cache: "npm" でキャッシングが有効化されます。基本的な使い方は互換性があるため、v4 からの移行は容易です。
キャッシュの仕組み
package-lock.jsonのハッシュ値をキーとして使用- ファイルが変更されない限り、同じキャッシュが再利用される
~/.npmディレクトリがキャッシュされる
2. テスト・Linter の統合
ビルドプロセスに、テストや静的解析(Linter)を組み込むことができます。
- name: Run tests
run: npm test
- name: Run linter
run: npm run lintこれにより、品質の低いコードが本番環境にデプロイされるのを防げます。
3. ビルドプロセスの完全制御
複雑なビルド要件(環境変数の設定、複数ステップのビルド、モノレポ対応など)に柔軟に対応できます。
4. デプロイの高速化
依存関係のキャッシュにより、2 回目以降のデプロイが大幅に高速化されます。
実装手順
Step 1: ワークフローファイルの作成
.github/workflows/frontend-deploy.yml を作成します。
name: Frontend SWA Deploy
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-22.04
environment: production
steps:
# 1. リポジトリをチェックアウト
- name: Checkout repository
uses: actions/checkout@v4
# 2. Node.js のセットアップ(キャッシュあり)
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
cache: "npm"
cache-dependency-path: "application/frontend/package-lock.json"
# 3. 依存関係のインストール
- name: Install dependencies
run: |
cd application/frontend
npm ci
# 4. テストとLinterの実行(オプション)
- name: Run tests
run: |
cd application/frontend
npm test
- name: Run linter
run: |
cd application/frontend
npm run lint
# 5. ビルド実行
- name: Build frontend
run: |
cd application/frontend
npm run build
# 6. Azure Static Web Apps へデプロイ
- name: Deploy to Azure Static Web Apps
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_DEPLOY_TOKEN }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
action: "upload"
app_location: "./application/frontend/out"
output_location: ""
skip_app_build: true # 重要: Oryx ビルドをスキップStep 2: デプロイトークンの取得
- Azure Portal にアクセス
- 対象の Static Web Apps リソースを開く
- 左メニューから「管理」を選択
- 「デプロイトークン」をコピー
Step 3: GitHub Secrets の設定
- GitHub リポジトリの Settings → Secrets and variables → Actions
- New repository secret をクリック
- 以下を設定:
- Name:
AZURE_SWA_DEPLOY_TOKEN - Secret: 手順 2 でコピーしたトークンを貼り付け
- Name:
- Add secret をクリック
セキュリティのベストプラクティス
デプロイトークンを安全に管理するための推奨事項:
1. 環境レベルのシークレット管理
リポジトリレベルではなく、GitHub 環境(staging、production)ごとにトークンを管理することを推奨します。
- Settings → Environments → New environment で環境を作成
- 環境ごとに異なるトークンを設定
これにより、環境ごとのアクセス制御が可能になり、誤ったデプロイを防げます。
2. 定期的なローテーション
トークンは定期的に再生成することを推奨します。
- Azure Portal → Static Web Apps → 管理 → デプロイトークンの再生成
- GitHub Secrets を更新
3. 漏洩時の対応
トークンが漏洩した場合は、即座に再生成してください。
- Azure Portal でトークンを再生成
- GitHub Secrets を更新すれば、次回デプロイから新しいトークンが使用されます
重要な設定ポイント
skip_app_build: true
この設定により、Oryx によるビルドをスキップし、既にビルド済みのファイルをそのままデプロイします。
skip_app_build: trueapp_location の指定
skip_app_build: true を使用する場合、ビルド済みファイルのディレクトリを指定します。
app_location: "./application/frontend/out" # Next.js の場合output_location は空文字列
skip_app_build: true と併用する場合は空文字列に設定します。
output_location: ""npm ci の使用
npm install ではなく、npm ci を使用することを強く推奨します。
# ❌ 避けるべき
- run: npm install
# ✅ 推奨
- run: npm ci理由:
npm ciはpackage-lock.jsonを厳密に再現- より高速で、CI/CD 環境に最適化されている
node_modulesを削除してからインストールするため、クリーンな環境が保証される
モノレポ構成での最適化
モノレポの場合、変更があったディレクトリのみビルドするように paths フィルタを設定できます。
on:
push:
branches:
- main
paths:
- "application/frontend/**"
- ".github/workflows/frontend-deploy.yml"メリット:
- フロントエンドの変更時のみワークフローが実行される
- 無駄なビルドを削減
- GitHub Actions の実行時間を節約
補足: SWA CLI を使用したデプロイ方法
公式の Azure/static-web-apps-deploy@v1 アクションを使わず、SWA CLI を直接使用する方法もあります。
実装例
- name: Install SWA CLI
run: npm install -g @azure/static-web-apps-cli
- name: Deploy with SWA CLI
run: |
swa deploy ./application/frontend/out \
--deployment-token ${{ secrets.AZURE_SWA_DEPLOY_TOKEN }} \
--env productionメリット・デメリット
メリット:
- ✅ GitHub Actions のキャッシュ機能を利用できる
- ✅ ローカル開発でも同じ CLI を使用できる(開発体験の統一)
- ✅ デプロイプロセスの細かい制御が可能
デメリット:
- ❌ SWA CLI への深い理解が必要(学習コスト)
- ❌ 公式アクションに比べて設定が複雑
- ❌ CLI のバージョン管理が必要
推奨の使い分け
- 公式アクション(
Azure/static-web-apps-deploy@v1)を推奨- カスタマイズ箇所が少なく、保守性が高い
- 本記事で紹介した
skip_app_build: trueパターンで十分高速
- SWA CLI が向いているケース
- ローカルで既に SWA CLI を使って開発している
- デプロイプロセスに特殊な要件がある
- CLI の細かい制御機能が必要
結論: ほとんどのケースでは、公式アクションをアップローダーとして利用する方法で十分です。
認証方法の選択:デプロイトークン vs OIDC
デプロイトークン方式(推奨)
特徴
- ✅ シンプルで設定が簡単
- ✅ Azure Static Web Apps の標準的な認証方法
- ✅ 安定性が高い
- ❌ トークンの管理が必要
使い方
- uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_SWA_DEPLOY_TOKEN }}OIDC Federated Credentials(2025年10月時点)
現状
Azure Static Web Apps は、デプロイ認証において OIDC(OpenID Connect)をネイティブサポートしていません(2025 年 1 月時点)。
補足: ユーザー認証用の OIDC(Auth0、Azure AD B2C など)は Standard プランで利用可能です。ここで述べているのは、GitHub Actions からのデプロイ時の認証に関する制限です。
他の Azure サービス(App Service、Container Instances など)では、デプロイ認証における OIDC がサポートされていますが、Static Web Apps では未対応です。
参考: GitHub Issue #1304 – Add Federated Credentials support
回避策の存在とリスク
OIDC トークンを使って Azure CLI で認証し、デプロイトークンを動的に取得する方法は存在しますが:
- ⚠️ トークンのマスキング設定ミスによるリークリスク
- ⚠️ 設定が複雑
- ⚠️ 現時点では推奨されない
推奨事項
2025 年 1 月時点では、デプロイトークン方式が最も安全で信頼性の高い方法です。
OIDC 対応については、コミュニティから強く要望されており、将来的にサポートされる可能性は高いですが、現時点ではまだ実装されていません。
トラブルシューティング
問題 1: キャッシュが効かない
症状
2 回目以降のビルドでも npm ci に時間がかかる
原因
cache-dependency-path が指定されていない、または間違っている
解決策
# ❌ 間違った設定
- uses: actions/setup-node@v4
with:
cache: "npm"
# cache-dependency-path が指定されていない
# ✅ 正しい設定
- uses: actions/setup-node@v4
with:
cache: "npm"
cache-dependency-path: "package-lock.json"モノレポの場合は、正しいパスを指定します:
cache-dependency-path: "application/frontend/package-lock.json"問題 2: デプロイが失敗する
症状
Error: No such file or directory原因
skip_app_build: true を使用しているのに、app_location が正しくない
解決策
# ❌ 間違った設定
app_location: "/" # ソースコードのパス
skip_app_build: true
# ✅ 正しい設定
app_location: "./application/frontend/out" # ビルド済みディレクトリ
skip_app_build: true
output_location: ""問題 3: ビルドコマンドが見つからない
症状
npm run build: command not found原因
package.json に build スクリプトが定義されていない
解決策
package.json に build スクリプトを追加します:
{
"scripts": {
"build": "next build"
}
}または、ワークフローで直接コマンドを指定します:
- name: Build frontend
run: next build問題 4: Actions のキャッシュサイズ超過
症状
Warning: Cache size exceeded limit原因
node_modules が大きすぎる
解決策
setup-node のキャッシュは ~/.npm をキャッシュするため、通常は問題ありません。
もし問題が発生する場合は、不要な devDependencies を削除するか、キャッシュを無効化します。キャッシュを無効化すると、カスタムビルドを組む意味が大幅に減ってしまいます。おそらくですが、この事象が頻発する場合はOryxのビルドも失敗するんちゃうかな?って思っとります。
問題 5: ビルドタイムアウト
症状
Error: Build timed out after 15 minutes原因
Azure Static Web Apps のビルドには 15 分の制限があります
解決策
カスタムビルド(本記事の方法)に移行することで、この制限を回避できます。GitHub Actions 側でビルドを行うため、Azure SWA 側のタイムアウトは影響しません。
まとめ
今回は、Azure Static Web Apps のデプロイを高速化するための、GitHub Actions カスタムビルドの実装方法をご紹介しました。
カスタムビルドを導入すべきケース
小規模プロジェクト・個人開発
- デフォルトの Oryx ビルドで十分
- シンプルさを優先
中規模以上のプロジェクト・チーム開発
- カスタムビルドを推奨
- キャッシュによる高速化の恩恵が大きい
- テスト・Linter の統合で品質向上
エンタープライズプロジェクト
- カスタムビルド必須
- 並列ジョブでテスト・ビルドを分離
- モノレポ構成で paths フィルタ活用
- デプロイ環境の分離(本番・ステージング)
カスタムビルドのメリット再確認
| 項目 | Oryx ビルド | カスタムビルド |
|---|---|---|
| 依存関係キャッシュ | ❌ なし | ✅ あり |
| テスト実行 | ❌ 不可 | ✅ 可能 |
| Linter 実行 | ❌ 不可 | ✅ 可能 |
| ビルド時間 | 遅い | 速い(2 回目以降) |
| カスタマイズ性 | 低い | 高い |
| セットアップ難易度 | 簡単 | やや複雑 |
参考リンク
- Azure Static Web Apps – Build Configuration(公式ドキュメント)
- GitHub Actions – setup-node
- Microsoft Oryx Repository
- Azure Static Web Apps: build app externally – johnnyreilly
この記事が、Azure Static Web Apps のデプロイを高速化する一助となれば幸いです。
カスタムビルドを導入することで、デプロイ時間の短縮だけでなく、テストや Linter の統合による品質向上など、開発体験が大きく向上します。
ぜひ、皆さんのプロジェクトでもお試しください!

