基本概念と全体像
GitHub Actions を使った Pages デプロイは「ビルド」と「デプロイ」の2段階で構成されます。まずこの流れを理解しておくと、あらゆるフレームワークに応用できます。
ワークフローの流れ
- トリガー(push / tag / PR など)でワークフロー開始
- Checkout でリポジトリを Runner に取得
- Setup(Node / Hugo / Python など環境構築)
- Build で静的ファイルを生成
- Upload artifact で成果物を一時保存
- Deploy で GitHub Pages に公開
必須 permissions
以下の3行はほぼすべての Pages ワークフローに必要です。
permissions:
contents: read
pages: write
id-token: write
contents: read— リポジトリ読み取りpages: write— Pages への書き込みid-token: write— OIDC トークン発行(deploy-pages で必須)
主要アクション一覧
| アクション | 役割 | 備考 |
|---|---|---|
actions/checkout@v4 | リポジトリをチェックアウト | ほぼ必須 |
actions/configure-pages@v5 | Pages のベースURL等を設定 | ビルド前に実行 |
actions/upload-pages-artifact@v3 | 成果物を一時アップロード | path に出力ディレクトリを指定 |
actions/deploy-pages@v4 | Pages にデプロイ | needs で build に依存 |
actions/setup-node@v4 | Node.js 環境構築 | cache 指定で高速化 |
actions/jekyll-build-pages@v1 | Jekyll ビルド | GitHub公式 |
peaceiris/actions-hugo@v3 | Hugo セットアップ | コミュニティ製 |
基本ワークフロー(静的ファイルそのまま)
ビルド不要な HTML/CSS/JS ファイルをそのままデプロイする場合。リポジトリルートがドキュメントルートになります。
name: Deploy to GitHub Pages
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: '.'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
path: '.' はリポジトリルート全体をアップロードします。path には index.html が存在するディレクトリを必ず指定してください。
Node.js ビルド & デプロイ
npm プロジェクトの汎用テンプレートです。Vite / React / Vue / 純粋なビルドツールなどに対応します。
name: Build and Deploy
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './dist'
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
各フレームワークの出力ディレクトリ
| フレームワーク | path | 備考 |
|---|---|---|
| Vite | ./dist | デフォルト |
| Create React App | ./build | |
| Vue CLI | ./dist | |
| Next.js(static) | ./out | next.config で output: 'export' 必須 |
| Astro | ./dist | |
| Nuxt(static) | ./.output/public | |
| SvelteKit(static) | ./build | adapter-static 必須 |
| Docusaurus | ./build | |
| Gatsby | ./public | |
| Remix(static) | ./build/client |
Next.js(Static Export)
Next.js を GitHub Pages で動かすには「Static Export」が必要です。SSR は Pages で直接動作しません。
まず next.config.js を以下のように設定します。
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
distDir: 'dist',
images: {
unoptimized: true, // Pagesでは必須
},
}
module.exports = nextConfig
name: Deploy Next.js
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
app/api や pages/api)は Static Export では生成されません。サーバー機能が必要な場合は Vercel や Cloudflare Pages を検討してください。
Astro
Astro はデフォルトで静的出力なので、設定が比較的シンプルです。
import { defineConfig } from 'astro/config'
export default defineConfig({
site: 'https://username.github.io',
base: '/repo-name', // プロジェクトサイトの場合のみ
})
name: Deploy Astro
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
Vite(vanilla / React / Vue / Preact)
プロジェクトサイト(username.github.io/repo-name)の場合、base の設定が必須です。
import { defineConfig } from 'vite'
export default defineConfig({
base: '/repo-name/', // 末尾スラッシュ必須
})
username.github.io)の場合は base: '/' または省略可能です。
name: Deploy Vite
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
Jekyll
name: Deploy Jekyll site to Pages
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Build Jekyll
uses: actions/jekyll-build-pages@v1
with:
source: ./
destination: ./_site
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
_site ディレクトリをデプロイする方法を使ってください。
Hugo
name: Deploy Hugo
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true # テーマがサブモジュールの場合必須
fetch-depth: 0 # .GitInfo / Lastmod 用
- uses: actions/setup-go@v5
with:
go-version: '1.22'
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: 'latest'
extended: true
- name: Build
run: hugo --minify
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: './public'
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
actions/setup-go も必要です。
Nuxt(Static)
export default defineNuxtConfig({
ssr: false, // または prerender 設定
nitro: {
output: {
publicDir: '.output/public'
}
}
})
name: Deploy Nuxt
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx nuxt generate # 静的生成
- uses: actions/upload-pages-artifact@v3
with:
path: ./.output/public
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
SvelteKit(adapter-static)
import adapter from '@sveltejs/adapter-static'
export default {
kit: {
adapter: adapter({
pages: 'build',
assets: 'build',
fallback: undefined // SPA の場合は 'index.html'
})
}
}
name: Deploy SvelteKit
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./build
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
Docusaurus
const config = {
url: 'https://username.github.io',
baseUrl: '/repo-name/',
organizationName: 'username',
projectName: 'repo-name',
deploymentBranch: 'gh-pages', // 手動デプロイ時用(Actionsでは不要)
trailingSlash: false,
}
module.exports = config
name: Deploy Docusaurus
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./build
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
MkDocs(Python)
name: Deploy MkDocs
on:
push:
branches: ["main"]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: pip
- name: Install dependencies
run: |
pip install mkdocs mkdocs-material
- name: Build
run: mkdocs build
- uses: actions/upload-pages-artifact@v3
with:
path: ./site
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
site_dir を変更していない場合、デフォルトの ./site が出力先です
応用テクニック
リリース時のみデプロイ
on:
push:
tags:
- 'v*'
バージョンタグを push したときだけ本番デプロイしmain への push ではステージングに出す、という運用に使えます。
workflow_dispatch
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
default: 'production'
type: choice
options:
- production
- staging
ビルド時に API キーや環境変数を渡す
jobs:
build:
runs-on: ubuntu-latest
env:
VITE_API_URL: ${{ vars.API_URL }}
VITE_API_KEY: ${{ secrets.API_KEY }}
steps:
- run: npm run build
vars— リポジトリ設定 > Variables で管理(非機密)secrets— リポジトリ設定 > Secrets で管理(機密)- Vite の場合は
VITE_プレフィックスが必要です - Next.js の場合は
NEXT_PUBLIC_プレフィックスが必要です
CNAME の扱い
方法1:ビルド後に生成
- run: npm run build
- run: echo 'www.example.com' > ./dist/CNAME
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
方法2:リポジトリに CNAME ファイルを置いてコピー
# public/CNAME または src/CNAME を
# ビルド時に dist/ へコピーする設定を各フレームワークで行う
ビルド高速化
Node.js(npm)
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
Hugo
- uses: actions/cache@v4
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go
同時実行制御
concurrency:
group: "pages"
cancel-in-progress: true
group: "pages"— Pages デプロイジョブを1つに制限cancel-in-progress: true— 新しい push が来たら古いビルドをキャンセル(節約)cancel-in-progress: false— 古いビルドは最後まで実行(安全)
特定条件でのみ実行
jobs:
deploy:
if: github.ref == 'refs/heads/main'
# または
if: startsWith(github.ref, 'refs/tags/v')
# または
if: github.event_name == 'workflow_dispatch'
SPA / カスタム 404 の設定
GitHub Pages は 404.html を自動的にエラーページとして使います。SPA の場合は 404.html を index.html と同じ内容にするか、各フレームワークの推奨方法に従てください。
- Vite SPA:
dist/404.htmlをindex.htmlのコピーにする - Vue Router(history mode):
public/404.htmlにフォールバック用 HTML を配置 - Next.js Static Export:
not-found.tsxが自動で404.htmlを生成
トラブルシューティング
deploy-pages で失敗
permissions に id-token: write と pages: write が不足しています。リポジトリ設定で「Read and write permissions」が有効になっているか確認してください。
デプロイ後に 404
pathにindex.htmlのあるディレクトリを指定しているか- プロジェクトサイトで
base/baseUrlの設定を忘れていないか - Pages の Source が GitHub Actions に設定されているか
CSS/JS/画像が 404
プロジェクトサイト(/repo-name/)の場合、絶対パス(/assets/...)ではなく相対パス(./assets/...)または base 設定を使う必要があります。Vite / Astro / Next.js などの base 設定を確認してください。
ビルド成功、デプロイ失敗
deployジョブにneeds: buildがあるか- artifact の
pathが存在しないディレクトリを指していないか - 同時実行制限に引っかかっていないか(数分待って再実行)
Next.js Image コンポーネントが崩れる
Static Export では next/image の最適化サーバーが動作しません。images.unoptimized: true を next.config.js に追加してください。
Hugo テーマが読み込めない
actions/checkout@v4でsubmodules: trueを設定- Git Submodule ではなく Go Modules を使っている場合は
actions/setup-goを追加