Workersのデプロイコマンド
Cloudflare Workersのデプロイコマンドと動作の違いについて説明します。Cloudflare Workersのデプロイコマンドと、それによってWorkerの動作がどう変わるかを整理します。各コマンドについて詳しく説明します。
wrangler dev — ローカル開発
Workerはデプロイされず、リクエストはローカルマシン上で処理されます。
フラグによる動作の違い:
- デフォルト(フラグなし) — Cloudflareのエッジにリクエストをプロキシしつつ、コードはローカルで実行。KV・D1などのバインディングはプレビュー用のサンドボックスを参照します。
--local— Miniflareを使った完全ローカルエミュレーション。インターネット不要で動作し、CI環境やオフライン開発に向いています。--remote— コードはローカルで動くが、KVやD1・R2などは本番リソースに接続。「ローカルコード × 本番データ」で検証したい場合に使います(本番データを読み書きするため注意が必要)。
wrangler deploy — 本番デプロイ
コードをビルドしてCloudflareのグローバルエッジネットワーク(300拠点以上)に即時配信します。デプロイ後、数秒以内に全世界に反映されます。
--env で環境を切り替え:
# wrangler.toml
[env.staging]
route = "staging.example.com/*"
vars = { API_URL = "https://api-staging.example.com" }
[env.production]
route = "example.com/*"
vars = { API_URL = "https://api.example.com" }
wrangler deploy --env staging→ stagingルートにデプロイ、stagingの変数を使用wrangler deploy --env production→ 本番ルートにデプロイ、本番の変数を使用
環境ごとに別のWorkerスクリプトとして登録されるため、stagingと本番が独立して動作します。
バージョン管理コマンド(段階的ロールアウト)
大規模なトラフィックへの影響を抑えながら新バージョンを公開したい場合に使います。
# バージョンをアップロードのみ(まだトラフィックには流れない)
wrangler versions upload
# トラフィックの10%だけ新バージョンに流す
wrangler versions deploy --version-id <id> --percentage 10
# 問題があれば即ロールバック
wrangler rollback
コマンドまとめ
| コマンド | Workerの動作 |
|---|---|
wrangler dev |
ローカル実行、デプロイなし |
wrangler dev --local |
完全オフライン実行 |
wrangler dev --remote |
ローカルコード+本番リソース |
wrangler deploy |
全エッジに即時反映 |
wrangler deploy --env staging |
staging環境のみに反映 |
wrangler versions upload |
バージョン登録のみ |
wrangler versions deploy |
割合指定で段階公開 |
wrangler rollback |
前バージョンに戻す |
バインディング設定について詳しく説明します。まず全体の構造をひと目で把握できる図から始め、その後各バインディングの詳細と実際のコードを説明します。Workerはすべてのバインディングを env オブジェクト経由で受け取ります。wrangler.toml での宣言と、コード内での使い方をバインディングごとに説明します。
KV Namespace — キー/バリューストア
グローバルに複製される超高速ストア。セッション、設定値、キャッシュに最適です。
# wrangler.toml
[[kv_namespaces]]
binding = "MY_KV" # env.MY_KV でアクセス
id = "xxxxxxxxxxxxxxxx" # 本番KVのID
preview_id = "yyyyyyyy" # wrangler dev 用のプレビューID
// Worker コード
export default {
async fetch(req: Request, env: Env) {
// 書き込み(TTLも指定可能)
await env.MY_KV.put("user:123", JSON.stringify({ name: "Taro" }), {
expirationTtl: 3600, // 1時間で自動削除
});
// 読み込み
const val = await env.MY_KV.get("user:123", { type: "json" });
// 削除
await env.MY_KV.delete("user:123");
// キー一覧(prefix で絞り込み可)
const list = await env.MY_KV.list({ prefix: "user:" });
}
};
注意点として、KVは結果整合性(書き込み後の伝播に最大60秒かかる場合あり)なので、即時一貫性が必要な用途にはD1を使います。
D1 Database — SQLite互換のリレーショナルDB
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "xxxxxxxxxxxxxxxx"
export default {
async fetch(req: Request, env: Env) {
// 単一クエリ
const user = await env.DB.prepare(
"SELECT * FROM users WHERE id = ?"
).bind(123).first();
// 複数行取得
const { results } = await env.DB.prepare(
"SELECT * FROM users WHERE active = 1"
).all();
// バッチ実行(複数クエリをアトミックに)
await env.DB.batch([
env.DB.prepare("INSERT INTO logs (msg) VALUES (?)").bind("started"),
env.DB.prepare("UPDATE users SET last_seen = ? WHERE id = ?")
.bind(Date.now(), 123),
]);
}
};
マイグレーションは wrangler d1 migrations apply DB --remote で実行します。
R2 Bucket — オブジェクトストレージ
S3互換で、画像・動画・大容量ファイルの保存に使います。エグレス(転送)料金が無料なのが大きな特徴です。
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-app-assets"
preview_bucket_name = "my-app-assets-dev" # dev用
export default {
async fetch(req: Request, env: Env) {
const url = new URL(req.url);
const key = url.pathname.slice(1); // "/image.png" → "image.png"
if (req.method === "PUT") {
// アップロード
await env.MY_BUCKET.put(key, req.body, {
httpMetadata: { contentType: req.headers.get("Content-Type") ?? "" },
customMetadata: { uploadedBy: "worker" },
});
return new Response("OK");
}
// ダウンロード
const obj = await env.MY_BUCKET.get(key);
if (!obj) return new Response("Not found", { status: 404 });
return new Response(obj.body, {
headers: { "Content-Type": obj.httpMetadata?.contentType ?? "application/octet-stream" },
});
}
};
Durable Objects — ステートフルなオブジェクト
リアルタイムコラボや WebSocket セッション管理など、「1箇所で状態を持つ」用途に使います。
[[durable_objects.bindings]]
name = "ROOM"
class_name = "ChatRoom"
[[migrations]]
tag = "v1"
new_classes = ["ChatRoom"]
// Durable Object クラス(同じWorkerファイルに定義)
export class ChatRoom {
state: DurableObjectState;
constructor(state: DurableObjectState) {
this.state = state;
}
async fetch(req: Request) {
// 永続ストレージへの読み書き
const count = (await this.state.storage.get<number>("count")) ?? 0;
await this.state.storage.put("count", count + 1);
return new Response(`count: ${count + 1}`);
}
}
// Worker 本体
export default {
async fetch(req: Request, env: Env) {
// IDによって「どのインスタンスか」を決定
const id = env.ROOM.idFromName("room-general");
const stub = env.ROOM.get(id);
return stub.fetch(req); // そのインスタンスへ転送
}
};
Queues — 非同期メッセージキュー
Workerをプロデューサー(送信側)とコンシューマー(受信側)に分けて設定します。
# 送信側(Producer)
[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-task-queue"
# 受信側(Consumer)
[[queues.consumers]]
queue = "my-task-queue"
max_batch_size = 10 # 一度に処理するメッセージ数
max_batch_timeout = 5 # 秒
max_retries = 3
export default {
// Producer: キューにメッセージを送る
async fetch(req: Request, env: Env) {
await env.MY_QUEUE.send({ userId: 123, action: "welcome_email" });
return new Response("Queued!");
},
// Consumer: バッチでメッセージを受け取る
async queue(batch: MessageBatch, env: Env) {
for (const msg of batch.messages) {
console.log(msg.body); // { userId: 123, action: "welcome_email" }
msg.ack(); // 処理完了を通知
}
}
};
Service Bindings — Worker間のゼロレイテンシ通信
複数のWorkerを連携させる際に使います。インターネットを経由せず内部で直接呼び出されます。
[[services]]
binding = "AUTH_SERVICE"
service = "my-auth-worker" # 別Workerの名前
export default {
async fetch(req: Request, env: Env) {
// 別のWorkerをHTTPリクエストと同じ感覚で呼び出せる
const authRes = await env.AUTH_SERVICE.fetch(
new Request("https://internal/verify", {
method: "POST",
body: JSON.stringify({ token: req.headers.get("Authorization") }),
})
);
if (!authRes.ok) return new Response("Unauthorized", { status: 401 });
return new Response("Hello, authenticated user!");
}
};
環境変数とシークレット
バインディングではないですが、実務でよく使う設定です。
[vars]
ENVIRONMENT = "production"
API_BASE_URL = "https://api.example.com"
シークレット(APIキーなど)はコマンドで設定し、wrangler.toml には書きません:
wrangler secret put STRIPE_SECRET_KEY
# → プロンプトが出て、値を入力するとCF側に暗号化保存される
コード内ではどちらも env.ENVIRONMENT、env.STRIPE_SECRET_KEY と同じように参照できます。