☁️
概念 #Cloudflare #Cloudflare Pages #Cloudflare KV #インフラ 📚 ブログサイト構築

ブログサイト構築 — Cloudflare ホスティング

Cloudflare Pages・Pages Functions・KV の連携構成。静的ホスティングと動的APIを Cloudflare エコシステム内で完結させる設計

Cloudflare ホスティング構成

本サイトは Cloudflare のサービスだけで完結している。

Cloudflare Pages(静的ファイル配信)
  └─ dist/**  →  全世界のエッジノードにキャッシュ

Cloudflare Pages Functions(動的 API)
  └─ functions/api/views/[slug].ts
      └─ Cloudflare KV(閲覧数の永続化)

Cloudflare Pages

役割

pnpm build で生成した dist/ を CDN で配信する。

デプロイ

npx wrangler pages deploy dist --project-name octomblog

Cloudflare の全世界エッジノードに自動配信される。 静的ファイルはエッジキャッシュされるため、オリジンへのアクセスはゼロ。

カスタムドメイン

Cloudflare DNS でドメインを管理し、Pages にカスタムドメインを紐づける。 Cloudflare DNS → Cloudflare Pages の接続は DNS 設定だけで完結(証明書自動発行)。

Cloudflare Pages Functions

役割

functions/ ディレクトリに配置した TypeScript ファイルが、ビルド時に自動的に Cloudflare Worker としてバンドルされる。

functions/
└── api/
    └── views/
        └── [slug].ts     ← /api/views/:slug にマッピング

実装例(閲覧数カウント)

interface Env {
  VIEWS: KVNamespace;  // wrangler.toml で KV バインディングを定義
}

export const onRequest: PagesFunction<Env> = async ({ params, request, env }) => {
  const slug = params.slug as string;
  const current = Number((await env.VIEWS.get(slug)) ?? 0);

  if (request.method === 'POST') {
    const next = current + 1;
    await env.VIEWS.put(slug, String(next));
    return new Response(JSON.stringify({ views: next }), {
      headers: { 'Content-Type': 'application/json' },
    });
  }

  return new Response(JSON.stringify({ views: current }), {
    headers: { 'Content-Type': 'application/json' },
  });
};

Pages Functions は Cloudflare Worker の実行環境(V8 Isolates)で動く。 Node.js ではなく Workers Runtime のため、利用できる API は制限される。

Workers Runtime の制限

機能Workers RuntimeNode.js
fetch✅ ネイティブサポート
localStorage / fs❌ 使えない
crypto✅ Web Crypto API
Node.js built-ins一部(node:* プレフィックス)

Cloudflare KV

役割

グローバル分散型 Key-Value ストア。閲覧数カウントの永続化に使用。

特性

特性詳細
整合性結果整合性(エッジ間での即時同期なし)
読み取り高速(エッジキャッシュ)
書き込み数秒〜数十秒の伝播遅延
用途読み取り頻度が高い・厳密な整合性が不要なデータ

閲覧数は多少の誤差があってもよいため、KV の結果整合性モデルが適している。

バインディング設定

wrangler.toml でバインディングを定義する。

[[kv_namespaces]]
binding = "VIEWS"
id = "xxxxxxxxxxxxxxxxxxxx"

Pages Functions の環境変数として env.VIEWS でアクセスできる。

デプロイフロー全体像

# 1. ビルド
pnpm build
# → dist/ に静的ファイル + OGP PNG が出揃う

# 2. Cloudflare Pages にデプロイ
npx wrangler pages deploy dist --project-name octomblog
# → 静的ファイル: Pages CDN にアップロード
# → functions/: Worker としてバンドル・デプロイ
# → KV: wrangler.toml のバインディング設定を参照

Cloudflare の無料枠

リソース無料枠
Pages ホスティング無制限の静的ファイル
Pages Functions100,000 リクエスト/日
KV 読み取り100,000 回/日
KV 書き込み1,000 回/日

個人ブログの規模では無料枠で十分運用できる。

関連