mcpField
C
cloudflare-pages

cloudflare-pages

github.com/bagelholeクラウド・DevOps1.2k333 回インストール23 週間前に更新
リポジトリ

cloudflare-pages について

フロントエンドおよびフルスタックプロジェクト向けの Cloudflare Pages デプロイスキルです。Wrangler や Git 連携による公開方法に加え、プレビュー、Pages Functions、バインディング、ドメイン設定を扱います。

主な機能

  1. 01Wrangler コマンドラインでのデプロイ
  2. 02Git 連携とプレビューデプロイ
  3. 03Pages Functions とミドルウェア
  4. 04KV、D1、R2 のバインディング
  5. 05カスタムドメイン、ヘッダー、リダイレクト
  6. 06CI/CD 設定例

活用シーン

  1. 01静的なフロントエンドサイトを公開
  2. 02プルリクエスト用のプレビューを生成
  3. 03サイトにエッジ API ルートを追加
  4. 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 連携

  1. Workers & Pages > Create application > Pages に移動します。
  2. GitHub または GitLab アカウントを連携します。
  3. リポジトリを選択し、次の項目を設定します。
    • Production branch:main
    • Build command:npm run build
    • Build output directory:dist(フレームワークに応じて build、.next、public)
  4. 環境ごと(Production と Preview)に環境変数を設定します。
フレームワークのプリセット

Cloudflare はフレームワークを自動検出します。必要に応じて変更してください。

フレームワークビルドコマンド出力ディレクトリ
React CRAnpm run buildbuild
Vitenpm run builddist
Next.jsnpx @cloudflare/next-on-pages.vercel/output/static
Astronpm run builddist
Hugohugopublic
SvelteKitnpm 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 の一般的な設定パターン

コメント