Azure Static Web Apps のデプロイを高速化!GitHub Actions カスタムビルドのすすめ

目次

はじめに

ども!先輩社員から 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 は以下のように動作します:

  1. リポジトリの内容を分析
  2. 使用されているプログラミング言語・フレームワークを検出
  3. 適切なビルドコマンドを自動実行

具体例(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: デプロイトークンの取得

  1. Azure Portal にアクセス
  2. 対象の Static Web Apps リソースを開く
  3. 左メニューから「管理」を選択
  4. デプロイトークン」をコピー

Step 3: GitHub Secrets の設定

  1. GitHub リポジトリの SettingsSecrets and variablesActions
  2. New repository secret をクリック
  3. 以下を設定:
    • Name: AZURE_SWA_DEPLOY_TOKEN
    • Secret: 手順 2 でコピーしたトークンを貼り付け
  4. 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: true

app_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 cipackage-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.jsonbuild スクリプトが定義されていない

解決策

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 のデプロイを高速化する一助となれば幸いです。

カスタムビルドを導入することで、デプロイ時間の短縮だけでなく、テストや Linter の統合による品質向上など、開発体験が大きく向上します。

ぜひ、皆さんのプロジェクトでもお試しください!

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です