cloudflare-pages について
フロントエンドおよびフルスタックプロジェクト向けの Cloudflare Pages デプロイスキルです。Wrangler や Git 連携による公開方法に加え、プレビュー、Pages Functions、バインディング、ドメイン設定を扱います。
主な機能
- 01Wrangler コマンドラインでのデプロイ
- 02Git 連携とプレビューデプロイ
- 03Pages Functions とミドルウェア
- 04KV、D1、R2 のバインディング
- 05カスタムドメイン、ヘッダー、リダイレクト
- 06CI/CD 設定例
活用シーン
- 01静的なフロントエンドサイトを公開
- 02プルリクエスト用のプレビューを生成
- 03サイトにエッジ API ルートを追加
- 04ドメイン、ヘッダー、リダイレクトを設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill cloudflare-pagesインストール後、Claude Code で/cloudflare-pagesを入力して読み込まれたか確認します。
詳細
Cloudflare Pages
Cloudflare のネットワーク上で、プレビュービルド、エッジ関数、グローバル CDN 配信を利用してフロントエンドプロジェクトをデプロイします。
使用する場面
- 静的サイト(React、Vue、Astro、Hugo、Next.js の静的エクスポート)をデプロイする場合。
- サーバー側ロジックに Pages Functions を使用するフルスタックアプリケーション。
- プルリクエストごとにプレビューを自動デプロイする必要があるプロジェクト。
- カスタムドメインと TLS を備えた、設定不要の CDN を利用したいチーム。
- Vercel、Netlify、GitHub Pages から Cloudflare のエコシステムへ移行する場合。
前提条件
- Node.js 18+ と npm がローカルにインストールされていること。
- Cloudflare アカウント(ほとんどのプロジェクトでは無料プランで利用できます)。
- Wrangler CLI がインストールされていること:
npm install -g wrangler。 wrangler loginまたはCLOUDFLARE_API_TOKEN環境変数で認証済みであること。- Git リポジトリ(ダッシュボード連携の場合は GitHub または GitLab)にソースコードがあること。
Wrangler でのプロジェクト設定
新しいプロジェクトの作成
# Create a new Pages project
npx wrangler pages project create my-site
# List existing projects
npx wrangler pages project list
# Delete a project (removes all deployments)
npx wrangler pages project delete my-site
ローカルのビルド出力からデプロイ
# Build your framework first
npm run build
# Deploy the output directory
npx wrangler pages deploy dist --project-name=my-site
# Deploy with a custom branch name (triggers preview URL)
npx wrangler pages deploy dist --project-name=my-site --branch=feature-auth
# Deploy and get the deployment URL in JSON
npx wrangler pages deploy dist --project-name=my-site --branch=main 2>&1 | tail -1
デプロイの一覧表示と管理
# List recent deployments
npx wrangler pages deployment list --project-name=my-site
# Tail live logs from a deployment
npx wrangler pages deployment tail --project-name=my-site --environment=production
ダッシュボードでの Git 連携
- Workers & Pages > Create application > Pages に移動します。
- GitHub または GitLab アカウントを連携します。
- リポジトリを選択し、次の項目を設定します。
- Production branch:
main - Build command:
npm run build - Build output directory:
dist(フレームワークに応じてbuild、.next、public)
- Production branch:
- 環境ごと(Production と Preview)に環境変数を設定します。
フレームワークのプリセット
Cloudflare はフレームワークを自動検出します。必要に応じて変更してください。
| フレームワーク | ビルドコマンド | 出力ディレクトリ |
|---|---|---|
| React CRA | npm run build | build |
| Vite | npm run build | dist |
| Next.js | npx @cloudflare/next-on-pages | .vercel/output/static |
| Astro | npm run build | dist |
| Hugo | hugo | public |
| SvelteKit | npm run build | .svelte-kit/cloudflare |
プレビューのデプロイ
本番環境以外のブランチには、それぞれ固有のプレビュー URL が自動的に割り当てられます。
# URL format for preview deployments
https://<commit-hash>.<project-name>.pages.dev
https://<branch-name>.<project-name>.pages.dev
ブランチベースのアクセス制御
# Set preview branch patterns in wrangler.toml (Pages-specific)
# Or configure via dashboard: Settings > Builds & deployments
# Include branches: feature/*, staging
# Exclude branches: dependabot/*
プルリクエストへのプレビューコメント
Cloudflare Pages GitHub App を有効にすると、デプロイ URL を PR コメントとして投稿できます。Settings > Builds & deployments > Preview comment で設定してください。
Pages Functions
Pages Functions を使うと、静的サイトとともにデプロイされるサーバー側ロジックを利用できます。プロジェクトのルートにある functions/ ディレクトリにファイルを配置してください。
基本的な API ルート
// functions/api/hello.ts
export const onRequestGet: PagesFunction = async (context) => {
return new Response(JSON.stringify({ message: "Hello from the edge" }), {
headers: { "Content-Type": "application/json" },
});
};
// functions/api/users/[id].ts — dynamic route parameter
export const onRequestGet: PagesFunction = async (context) => {
const userId = context.params.id;
return new Response(JSON.stringify({ userId }), {
headers: { "Content-Type": "application/json" },
});
};
ミドルウェア
// functions/_middleware.ts — runs before all routes
export const onRequest: PagesFunction = async (context) => {
const authHeader = context.request.headers.get("Authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return new Response("Unauthorized", { status: 401 });
}
return context.next();
};
バインディングを使用する Functions
// functions/api/data.ts — using KV and D1 bindings
interface Env {
MY_KV: KVNamespace;
MY_DB: D1Database;
MY_BUCKET: R2Bucket;
}
export const onRequestGet: PagesFunction<Env> = async (context) => {
// Read from KV
const cached = await context.env.MY_KV.get("key");
if (cached) return new Response(cached);
// Query D1
const result = await context.env.MY_DB.prepare(
"SELECT * FROM items LIMIT 10"
).all();
// Cache in KV
await context.env.MY_KV.put("key", JSON.stringify(result.results), {
expirationTtl: 300,
});
return Response.json(result.results);
};
Wrangler の設定
# wrangler.toml — Pages project configuration
name = "my-site"
compatibility_date = "2024-09-01"
pages_build_output_dir = "dist"
# KV namespace binding
[[kv_namespaces]]
binding = "MY_KV"
id = "abc123def456"
# D1 database binding
[[d1_databases]]
binding = "MY_DB"
database_name = "my-app-db"
database_id = "xxxx-yyyy-zzzz"
# R2 bucket binding
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "app-assets"
# Environment variables
[vars]
API_BASE_URL = "https://api.example.com"
ヘッダーとリダイレクト
カスタムヘッダー
# public/_headers
/assets/*
Cache-Control: public, max-age=31536000, immutable
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'
/api/*
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
リダイレクト
# public/_redirects
/old-page /new-page 301
/blog/:slug /posts/:slug 301
/docs/* https://docs.example.com/:splat 302
/home / 302
カスタムドメイン
# Add a custom domain via Cloudflare dashboard:
# Pages project > Custom domains > Set up a custom domain
# Or via API
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/my-site/domains" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"www.example.com"}'
CI/CD 連携
GitHub Actions
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
pull_request:
jobs:
deploy:
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: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy dist --project-name=my-site
トラブルシューティング
| 症状 | 原因 | 対処方法 |
|---|---|---|
| メモリ不足でビルドが失敗する | ビルドが 1 GB RAM の上限を超えている | 依存関係を減らす。NODE_OPTIONS=--max_old_space_size=768 を使用する |
| Functions が 404 を返す | functions/ ディレクトリがプロジェクトのルートにない | functions/ を src/ 内ではなく、リポジトリのルートに移動する |
| プレビュー URL に古いコンテンツが表示される | ブラウザーキャッシュ、または古いデプロイ | 強制再読み込みする。デプロイ一覧で最新のコミットハッシュを確認する |
| カスタムドメインで SSL エラーが表示される | DNS が Cloudflare 経由でプロキシされていない | CNAME レコードでオレンジ色の雲(プロキシ)を有効にする |
_headers ファイルが無視される | ファイルがビルド出力ディレクトリにない | ビルド時に dist/ へコピーされるよう、public/ に配置する |
| Functions でバインディングが未定義になる | wrangler.toml またはダッシュボードの設定がない | wrangler.toml にバインディングを追加し、再デプロイする |
| 関数のサイズが 1 MB の上限を超える | バンドルされる依存関係が多すぎる | ツリーシェイクする。サイズの大きな依存関係を KV または R2 に移す |
関連スキル
- cloudflare-workers - エッジのバックエンドロジックと API ルート
- cloudflare-r2 - アセットやアップロード用のオブジェクトストレージ
- cloudflare-zero-trust - Access ポリシーでプレビュー環境へのデプロイを保護
- cdn-setup - CDN の一般的な設定パターン
コメント
Markdown 対応