GitHub Pages
Webホスティングプラットフォーム
GitHub Pages
概要
GitHub PagesはGitHubリポジトリから直接ホスティングできる静的サイト向けサービスです。Jekyll統合により、マークダウンからHTMLへの自動変換とブログ機能を提供し、オープンソースプロジェクトのドキュメントサイトやポートフォリオサイトで広く利用されています。GitHubとの緊密な統合により継続的に安定した需要を維持しています。
詳細
2008年にローンチされたGitHub Pagesは、GitHubの代表的な機能の一つとして多くの開発者に愛用されています。特にオープンソースプロジェクトのドキュメント、個人のポートフォリオサイト、技術ブログで人気。Jekyll(Ruby製静的サイトジェネレーター)との統合により、Markdownファイルを自動的にHTMLに変換し、テーマやプラグインの豊富なエコシステムを活用可能。2025年からはGitHub Actionsを使用したビルドプロセスに移行し、より柔軟なカスタマイゼーションと新しいJekyllバージョンの利用が可能になりました。
メリット・デメリット
メリット
- 完全無料: パブリックリポジトリでは無制限に利用可能
- GitHubとの統合: リポジトリ管理とホスティングが一体化
- Jekyll統合: Markdownからの自動HTML生成
- カスタムドメイン対応: 独自ドメインの設定が可能
- HTTPS対応: 自動SSL証明書発行
- GitHub Actions: 高度なビルドプロセスのカスタマイズ
- 豊富なテーマ: 数多くの美しいJekyllテーマが利用可能
デメリット
- 静的サイトのみ: サーバーサイド処理は不可
- ビルド制限: 月10GBのバンドウィズ制限
- Jekyll依存: 他のSSGを使用する際はGitHub Actions必須
- パフォーマンス: 他の専用CDNと比べて速度が劣る場合有り
- 機能制限: 高度な機能やプラグインに制約
参考ページ
書き方の例
基本的なセットアップとプロジェクト設定
# GitHub CLIでのリポジトリ作成
gh repo create my-website --public --clone
cd my-website
# Jekyll サイトの初期化
jekyll new . --force
bundle install
# GitHub Pagesの有効化(Settings > Pages)
# Source: Deploy from a branch または GitHub Actions
# 初期コミット
git add .
git commit -m "Initial Jekyll site"
git push origin main
# _config.yml - Jekyll基本設定
title: My Awesome Website
description: A great site built with Jekyll and hosted on GitHub Pages
baseurl: "" # リポジトリ名(例: "/my-website")
url: "https://username.github.io"
# GitHub Pages設定
github_username: your-username
repository: your-username/my-website
# Jekyll設定
markdown: kramdown
highlighter: rouge
theme: minima
# プラグイン設定
plugins:
- jekyll-feed
- jekyll-sitemap
- jekyll-seo-tag
- jekyll-redirect-from
# 除外ファイル
exclude:
- Gemfile
- Gemfile.lock
- node_modules
- vendor/bundle/
- vendor/cache/
- vendor/gems/
- vendor/ruby/
静的サイトデプロイ
# .github/workflows/jekyll.yml - Jekyll GitHub Actions
name: Build and deploy Jekyll site to GitHub Pages
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.1'
bundler-cache: true
cache-version: 0
- name: Setup Pages
id: pages
uses: actions/configure-pages@v4
- name: Build with Jekyll
run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}"
env:
JEKYLL_ENV: production
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./_site
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
フレームワーク統合(Next.js、React、Vue)
# .github/workflows/nextjs.yml - Next.js GitHub Actions
name: Deploy Next.js site to Pages
on:
push:
branches: ["main"]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
- name: Setup Pages
uses: actions/configure-pages@v4
with:
static_site_generator: next
- name: Restore cache
uses: actions/cache@v4
with:
path: |
.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}
- name: Install dependencies
run: npm ci
- name: Build with Next.js
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
// next.config.js - GitHub Pages対応
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
trailingSlash: true,
images: {
unoptimized: true
},
basePath: process.env.NODE_ENV === 'production' ? '/repository-name' : '',
assetPrefix: process.env.NODE_ENV === 'production' ? '/repository-name/' : '',
};
module.exports = nextConfig;
カスタムドメインとSSL
# カスタムドメインの設定
echo "example.com" > CNAME
git add CNAME
git commit -m "Add custom domain"
git push origin main
# DNS設定(CNAMEレコード)
# example.com -> username.github.io
# www.example.com -> username.github.io
# _config.yml - カスタムドメイン設定
url: "https://example.com"
baseurl: ""
# HTTPS強制
enforce_ssl: true
# カスタムドメイン用プラグイン
plugins:
- jekyll-redirect-from
# リダイレクト設定
redirect_from:
- /old-page/
- /another-old-page/
<!-- 404.html - カスタム404ページ -->
---
layout: default
permalink: /404.html
---
<div class="error-page">
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<a href="{{ site.baseurl }}/" class="btn">Go Home</a>
</div>
<script>
// SPA用のクライアントサイドルーティング
(function() {
var path = window.location.pathname;
var base = '{{ site.baseurl }}';
// GitHub Pagesでのルーティング処理
if (path !== base + '/404.html') {
window.location.replace(base + '/#' + path);
}
})();
</script>
サーバーレスファンクションとAPI
# .github/workflows/api-simulation.yml - 疑似API作成
name: Generate API Data
on:
push:
branches: [ main ]
schedule:
- cron: '0 0 * * *' # 毎日実行
jobs:
generate-data:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Generate API data
run: |
mkdir -p api
# ユーザーデータの生成
cat > api/users.json << 'EOF'
{
"users": [
{
"id": 1,
"name": "John Doe",
"email": "[email protected]",
"created_at": "${{ steps.date.outputs.date }}"
}
],
"total": 1,
"generated_at": "${{ steps.date.outputs.date }}"
}
EOF
# 統計データの生成
node -e "
const stats = {
page_views: Math.floor(Math.random() * 10000),
unique_visitors: Math.floor(Math.random() * 1000),
last_updated: new Date().toISOString()
};
require('fs').writeFileSync('api/stats.json', JSON.stringify(stats, null, 2));
"
- name: Commit and push
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add api/
git diff --staged --quiet || git commit -m "Update API data"
git push
// _includes/api-client.js - 静的APIクライアント
class StaticAPI {
constructor(baseUrl) {
this.baseUrl = baseUrl || '';
}
async get(endpoint) {
try {
const response = await fetch(`${this.baseUrl}/api/${endpoint}.json`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return await response.json();
} catch (error) {
console.error('API Error:', error);
return null;
}
}
// 検索機能(静的データベース)
async search(query, type = 'posts') {
const data = await this.get(type);
if (!data) return [];
const searchTerm = query.toLowerCase();
return data.filter(item =>
item.title.toLowerCase().includes(searchTerm) ||
item.content.toLowerCase().includes(searchTerm)
);
}
}
// 使用例
const api = new StaticAPI('{{ site.baseurl }}');
// ページ読み込み時のデータフェッチ
document.addEventListener('DOMContentLoaded', async () => {
const users = await api.get('users');
const stats = await api.get('stats');
// データの表示
if (users) {
document.getElementById('user-count').textContent = users.total;
}
if (stats) {
document.getElementById('page-views').textContent = stats.page_views;
}
});
CI/CDと本番最適化
# .github/workflows/optimization.yml - 最適化ワークフロー
name: Build and Optimize
on:
push:
branches: [ main ]
jobs:
build-and-optimize:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build Jekyll site
run: |
bundle install
bundle exec jekyll build
- name: Optimize images
run: |
npm install -g imagemin-cli imagemin-webp imagemin-mozjpeg imagemin-pngquant
imagemin "_site/**/*.{jpg,jpeg,png}" --out-dir="_site" --plugin=mozjpeg --plugin=pngquant
- name: Minify HTML/CSS/JS
run: |
npm install -g html-minifier clean-css-cli uglify-js
# HTML minification
find _site -name "*.html" -exec html-minifier --collapse-whitespace --remove-comments {} \;
# CSS minification
find _site -name "*.css" -exec cleancss -o {} {} \;
# JS minification
find _site -name "*.js" -exec uglifyjs {} -o {} \;
- name: Generate PWA files
run: |
cat > _site/manifest.json << 'EOF'
{
"name": "${{ github.repository }}",
"short_name": "Site",
"start_url": "{{ site.baseurl }}/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000"
}
EOF
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./_site
# Gemfile - Jekyll プラグイン設定
source "https://rubygems.org"
gem "jekyll", "~> 4.3.0"
gem "github-pages", group: :jekyll_plugins
group :jekyll_plugins do
gem "jekyll-feed"
gem "jekyll-sitemap"
gem "jekyll-seo-tag"
gem "jekyll-redirect-from"
gem "jekyll-paginate"
gem "jekyll-gist"
gem "jekyll-github-metadata"
gem "jekyll-include-cache"
gem "jekyll-compress-images"
gem "jekyll-minifier"
end
# Performance monitoring
gem "jekyll-analytics"
# Development
group :development do
gem "webrick"
end
# 開発・運用コマンド集
# ローカル開発
bundle exec jekyll serve --livereload --port 4000
# 本番ビルド
JEKYLL_ENV=production bundle exec jekyll build
# 依存関係更新
bundle update
# GitHub Pages互換性チェック
github-pages health-check
# サイト分析
bundle exec jekyll doctor
# プレビュー(GitHub Pages環境)
act -W .github/workflows/pages.yml