Use Cases

Claude CodeでCloudflare Workersを開発する実践ガイド

Claude Codeを活用したCloudflare Workersの開発手法を解説。KV、D1データベース、R2ストレージ、Durable Objectsまで実践的に紹介します。

Cloudflare Workers開発をClaude Codeで加速する

Cloudflare Workersは、Cloudflareのグローバルネットワーク上でJavaScript/TypeScriptを実行できるサーバーレスプラットフォームです。V8エンジンをベースとし、コールドスタートゼロで高速なレスポンスを実現します。Claude Codeを活用すれば、Workers特有のAPIやバインディングも効率的に扱えます。

プロジェクトの立ち上げ

> Cloudflare Workersのプロジェクトを作成して。
> HonoフレームワークとD1データベースを使う構成で。
npm create cloudflare@latest my-worker -- --template=hello-world
cd my-worker
npm install hono
# wrangler.toml
name = "my-api"
main = "src/index.ts"
compatibility_date = "2024-12-01"

[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

[[kv_namespaces]]
binding = "CACHE"
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

[[r2_buckets]]
binding = "STORAGE"
bucket_name = "my-bucket"

Honoを使ったAPI実装

> HonoフレームワークでCRUD APIを作って。
> D1データベースとの連携も実装して。
// src/index.ts
import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { jwt } from 'hono/jwt';

type Bindings = {
  DB: D1Database;
  CACHE: KVNamespace;
  STORAGE: R2Bucket;
  JWT_SECRET: string;
};

const app = new Hono<{ Bindings: Bindings }>();

app.use('/api/*', cors());

// 記事一覧
app.get('/api/posts', async (c) => {
  const { results } = await c.env.DB.prepare(
    'SELECT * FROM posts ORDER BY created_at DESC LIMIT 20'
  ).all();

  return c.json({ posts: results });
});

// 記事作成
app.post('/api/posts', async (c) => {
  const { title, content } = await c.req.json();

  const result = await c.env.DB.prepare(
    'INSERT INTO posts (title, content, created_at) VALUES (?, ?, datetime())'
  )
    .bind(title, content)
    .run();

  // キャッシュのクリア
  await c.env.CACHE.delete('posts:latest');

  return c.json({ id: result.meta.last_row_id }, 201);
});

// 画像アップロード(R2)
app.post('/api/upload', async (c) => {
  const formData = await c.req.formData();
  const file = formData.get('file') as File;

  if (!file) {
    return c.json({ error: 'File required' }, 400);
  }

  const key = `uploads/${Date.now()}-${file.name}`;
  await c.env.STORAGE.put(key, file.stream(), {
    httpMetadata: { contentType: file.type },
  });

  return c.json({ key, url: `/api/files/${key}` });
});

export default app;

D1データベースのマイグレーション

-- migrations/0001_create_tables.sql
CREATE TABLE IF NOT EXISTS posts (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  slug TEXT UNIQUE,
  published BOOLEAN DEFAULT FALSE,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_posts_slug ON posts(slug);
CREATE INDEX idx_posts_published ON posts(published, created_at);
# マイグレーションの実行
npx wrangler d1 migrations apply my-database

# ローカル開発
npx wrangler d1 migrations apply my-database --local
npx wrangler dev

KVキャッシュの活用

// src/cache.ts
export async function getCachedData<T>(
  kv: KVNamespace,
  key: string,
  fetcher: () => Promise<T>,
  ttl = 3600
): Promise<T> {
  const cached = await kv.get(key, 'json');
  if (cached) return cached as T;

  const data = await fetcher();
  await kv.put(key, JSON.stringify(data), { expirationTtl: ttl });
  return data;
}

// 使用例
app.get('/api/stats', async (c) => {
  const stats = await getCachedData(
    c.env.CACHE,
    'stats:daily',
    async () => {
      const { results } = await c.env.DB.prepare(
        'SELECT COUNT(*) as count FROM posts WHERE published = TRUE'
      ).all();
      return results[0];
    },
    300 // 5分キャッシュ
  );

  return c.json(stats);
});

デプロイとモニタリング

# デプロイ
npx wrangler deploy

# ログの確認
npx wrangler tail

# シークレットの設定
npx wrangler secret put JWT_SECRET

まとめ

Cloudflare Workersの充実したバインディングとClaude Codeを組み合わせれば、エッジで動作するフルスタックAPIを効率的に構築できます。サーバーレス関数ガイドエッジコンピューティング入門も参考にしてください。

Cloudflare Workersの詳細はCloudflare Workers公式ドキュメントを参照してください。

#Claude Code #Cloudflare Workers #エッジコンピューティング #サーバーレス #API