スキル一覧に戻る
biwakonbu

workers-development

by biwakonbu

Claude Code 用プラグイン

0🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: workers-development description: Cloudflare Workers の開発ガイド。アーキテクチャ、TypeScript/JavaScript 開発、バインディング、Service Bindings、Cron Triggers、Workers Assets について提供。Use when user asks about Workers development, edge functions, bindings, service bindings, cron triggers, or Workers runtime. Also use when user says Workers 開発, エッジ関数, バインディング, サービス連携. context: fork

Cloudflare Workers Development

概要

Cloudflare Workers は、世界330以上のデータセンターで動作するサーバーレスエッジコンピューティングプラットフォーム。 V8 Isolates ベースでコールドスタートがほぼゼロ、低レイテンシを実現。

アーキテクチャ

V8 Isolates

  • Chrome の V8 エンジンをベースにした軽量な実行環境
  • 各リクエストが独立した Isolate で実行
  • コンテナや VM より高速な起動

制限事項

項目Free プランPaid プラン
CPU 時間10ms50ms(バースト可)
メモリ128MB128MB
サブリクエスト50/リクエスト1000/リクエスト
スクリプトサイズ1MB10MB

基本構造

ES Modules 形式(推奨)

export interface Env {
  MY_KV: KVNamespace;
  DB: D1Database;
  MY_BUCKET: R2Bucket;
  AI: Ai;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);

    if (url.pathname === "/api/data") {
      const data = await env.MY_KV.get("key");
      return Response.json({ data });
    }

    return new Response("Hello Workers!");
  },

  async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext): Promise<void> {
    // Cron ジョブ
    ctx.waitUntil(doBackgroundWork(env));
  },

  async queue(batch: MessageBatch, env: Env, ctx: ExecutionContext): Promise<void> {
    // Queue consumer
    for (const message of batch.messages) {
      console.log(message.body);
      message.ack();
    }
  },
};

Service Worker 形式(レガシー)

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  return new Response("Hello!");
}

バインディング

Workers から他の Cloudflare サービスに接続するための設定。

wrangler.toml での設定

# KV
[[kv_namespaces]]
binding = "MY_KV"
id = "xxx"

# R2
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"

# D1
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxx"

# Durable Objects
[durable_objects]
bindings = [
  { name = "COUNTER", class_name = "Counter" }
]

# AI
[ai]
binding = "AI"

# Vectorize
[[vectorize]]
binding = "VECTORIZE"
index_name = "my-index"

# Service Bindings
[[services]]
binding = "AUTH"
service = "auth-worker"

# Queues
[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-queue"

# Analytics Engine
[[analytics_engine_datasets]]
binding = "ANALYTICS"
dataset = "my-dataset"

TypeScript 型定義

export interface Env {
  // KV
  MY_KV: KVNamespace;

  // R2
  MY_BUCKET: R2Bucket;

  // D1
  DB: D1Database;

  // Durable Objects
  COUNTER: DurableObjectNamespace;

  // AI
  AI: Ai;

  // Vectorize
  VECTORIZE: VectorizeIndex;

  // Service Bindings
  AUTH: Fetcher;

  // Queues
  MY_QUEUE: Queue;

  // 環境変数
  API_URL: string;

  // シークレット
  API_KEY: string;
}

Service Bindings

Workers 間の直接通信。HTTP オーバーヘッドなし。

設定

[[services]]
binding = "AUTH_SERVICE"
service = "auth-worker"
environment = "production"

使用例

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // 別の Worker を呼び出し
    const authResponse = await env.AUTH_SERVICE.fetch(
      new Request("https://auth/verify", {
        method: "POST",
        body: JSON.stringify({ token: "xxx" }),
      })
    );

    if (!authResponse.ok) {
      return new Response("Unauthorized", { status: 401 });
    }

    return new Response("Authorized!");
  },
};

Cron Triggers

定期実行ジョブ。

設定

[triggers]
crons = [
  "0 * * * *",      # 毎時
  "30 8 * * 1-5",   # 平日 8:30
  "0 0 1 * *",      # 毎月1日
]

ハンドラー

export default {
  async scheduled(
    event: ScheduledEvent,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void> {
    console.log(`Cron: ${event.cron}`);
    console.log(`Scheduled: ${new Date(event.scheduledTime)}`);

    // バックグラウンド処理
    ctx.waitUntil(
      env.DB.prepare("DELETE FROM logs WHERE created_at < ?")
        .bind(Date.now() - 7 * 24 * 60 * 60 * 1000)
        .run()
    );
  },
};

Workers Assets

静的ファイルの配信(Workers Sites の後継)。

設定

[assets]
directory = "./public"
binding = "ASSETS"  # オプション

動作

  1. リクエスト URL が静的ファイルに一致 → 自動配信
  2. 一致しない → Worker スクリプト実行

プログラムからのアクセス

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // アセットを取得
    const assetResponse = await env.ASSETS.fetch(request);

    if (assetResponse.status !== 404) {
      return assetResponse;
    }

    // カスタム404
    return new Response("Not Found", { status: 404 });
  },
};

ExecutionContext

waitUntil

レスポンス後もバックグラウンドで処理を継続。

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    // レスポンスを即座に返す
    const response = new Response("OK");

    // バックグラウンドでログ記録
    ctx.waitUntil(
      env.MY_KV.put("last_access", new Date().toISOString())
    );

    return response;
  },
};

passThroughOnException

エラー時にオリジンにフォールバック。

ctx.passThroughOnException();

Node.js 互換性

有効化

compatibility_flags = ["nodejs_compat"]

使用可能な API

import { Buffer } from "node:buffer";
import { createHash } from "node:crypto";
import { EventEmitter } from "node:events";

const hash = createHash("sha256").update("data").digest("hex");

互換性のあるモジュール

  • node:buffer
  • node:crypto
  • node:events
  • node:stream
  • node:util
  • node:assert
  • node:path

fetch API

外部 API 呼び出し

const response = await fetch("https://api.example.com/data", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${env.API_KEY}`,
  },
  body: JSON.stringify({ key: "value" }),
});

const data = await response.json();

リクエスト変換

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);
    url.hostname = "api.example.com";

    const modifiedRequest = new Request(url, {
      method: request.method,
      headers: request.headers,
      body: request.body,
    });

    return fetch(modifiedRequest);
  },
};

ミドルウェアパターン

type Middleware = (
  request: Request,
  env: Env,
  ctx: ExecutionContext,
  next: () => Promise<Response>
) => Promise<Response>;

const withAuth: Middleware = async (request, env, ctx, next) => {
  const token = request.headers.get("Authorization");
  if (!token) {
    return new Response("Unauthorized", { status: 401 });
  }
  return next();
};

const withCors: Middleware = async (request, env, ctx, next) => {
  const response = await next();
  response.headers.set("Access-Control-Allow-Origin", "*");
  return response;
};

// 使用
const middlewares = [withCors, withAuth];

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    let handler = async () => new Response("Hello!");

    for (const mw of middlewares.reverse()) {
      const next = handler;
      handler = () => mw(request, env, ctx, next);
    }

    return handler();
  },
};

テスト

Vitest(推奨)

import { env, createExecutionContext, waitOnExecutionContext } from "cloudflare:test";
import { describe, it, expect } from "vitest";
import worker from "./index";

describe("Worker", () => {
  it("returns hello", async () => {
    const request = new Request("https://example.com/");
    const ctx = createExecutionContext();
    const response = await worker.fetch(request, env, ctx);
    await waitOnExecutionContext(ctx);

    expect(response.status).toBe(200);
    expect(await response.text()).toBe("Hello!");
  });
});

vitest.config.ts

import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";

export default defineWorkersConfig({
  test: {
    poolOptions: {
      workers: {
        wrangler: { configPath: "./wrangler.toml" },
      },
    },
  },
});

デバッグ

console.log

console.log("Debug:", { key: value });
console.error("Error:", error);
console.time("operation");
// ...
console.timeEnd("operation");

wrangler tail

npx wrangler tail --format pretty

公式リソース

スコア

総合スコア

60/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です