← 戻る

Astro + Cloudflare Pages でフォーム処理を実装する


前提

  • Astro 5 で静的サイト生成(output: 'static'
  • Cloudflare Pages にデプロイ
  • フォーム送信後の webhook 処理が必要

実装パターン

1. Pages Functions の配置

functions/
  contact.ts          # POST /api/contact
  form-utils.ts       # 共通ロジック

2. Astro コンポーネント側

---
// src/components/ContactForm.astro
// フォーム validation / UX は astro:islands で React/Svelte
---
<form id="contact-form">
  <input name="name" required />
  <input name="email" type="email" required />
  <textarea name="message" required></textarea>
  <button type="submit">送信</button>
</form>

<script>
  document.getElementById('contact-form')?.addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    const response = await fetch('/api/contact', {
      method: 'POST',
      body: JSON.stringify(Object.fromEntries(formData))
    });
    // ...
  });
</script>

3. Pages Functions で webhook 実行

// functions/contact.ts
export const onRequest: PagesFunction = async (context) => {
  try {
    const { name, email, message } = await context.request.json();

    // Validation
    if (!name || !email || !message) {
      return new Response('Missing fields', { status: 400 });
    }

    // Webhook 実行
    const slackResponse = await fetch(
      context.env.SLACK_WEBHOOK_URL,
      {
        method: 'POST',
        body: JSON.stringify({
          text: `新規お問い合わせ\n名前: ${name}\nメール: ${email}\nメッセージ: ${message}`
        })
      }
    );

    if (!slackResponse.ok) {
      throw new Error('Slack webhook failed');
    }

    return new Response(
      JSON.stringify({ success: true }),
      { status: 200, headers: { 'Content-Type': 'application/json' } }
    );
  } catch (error) {
    console.error('Form submission error:', error);
    return new Response('Internal server error', { status: 500 });
  }
};

ポイント

  • 環境変数: wrangler.tomlenv セクションに Slack Webhook URL を定義
  • CORS: Astro 静的ファイルとエッジ関数は同一オリジン(CORS 不要)
  • キャッシング: Pages Functions は自動的にキャッシュされない(毎回実行)

メリット

  • サーバーレス・自動スケーリング
  • Google Firebase/Cloud Run より簡潔
  • Cloudflare Analytics Engine で リクエスト監視可能