Wrangler CLI完全ガイド:Cloudflare Workersの開発・デプロイ効率化
Wrangler CLI完全ガイド:Cloudflare Workersの開発・デプロイ効率化
Cloudflare Workersは、エッジコンピューティングを活用したサーバーレスプラットフォームとして急速に普及しています。その開発体験を支えるのがWrangler CLIです。本記事では、Wranglerを使った効率的な開発フローから本番デプロイまで、実践的なテクニックを網羅的に解説します。
Wrangler CLIとは
Wranglerは、Cloudflare Workersの公式コマンドラインツールです。プロジェクトの初期化、ローカル開発、テスト、デプロイまでをシームレスに行えます。
主な機能
- プロジェクト管理: テンプレートからの素早いセットアップ
- ローカル開発: Miniflareベースの高速な開発サーバー
- デプロイ管理: 複数環境への簡単なデプロイ
- KV/R2/D1操作: データストアの直接操作
- ログ確認: リアルタイムログストリーミング
- シークレット管理: 環境変数の安全な管理
インストールと初期設定
Node.js経由でのインストール
# npm
npm install -g wrangler
# pnpm
pnpm add -g wrangler
# yarn
yarn global add wrangler
# バージョン確認
wrangler --version
認証設定
# ブラウザで認証
wrangler login
# または、APIトークンを使用
wrangler config
# 環境変数での設定(CI/CD向け)
export CLOUDFLARE_API_TOKEN=your_token_here
APIトークンは、Cloudflareダッシュボードの「My Profile > API Tokens」から作成できます。必要な権限は「Edit Cloudflare Workers」です。
プロジェクトの作成
テンプレートからの作成
# 基本的なWorkerプロジェクト
wrangler init my-worker
# TypeScript + 各種オプション
wrangler init my-worker --type typescript
# 既存ディレクトリで初期化
cd existing-project
wrangler init
対話的なセットアップ
Wrangler 3以降では、対話的なプロンプトでプロジェクトをカスタマイズできます:
wrangler init my-advanced-worker
# ✔ Would you like to use TypeScript? (y/n) › yes
# ✔ Would you like to create a package.json? (y/n) › yes
# ✔ Would you like to use a template? (y/n) › yes
# ✔ Which template would you like to use? › hello-world
wrangler.tomlの設定
生成されたwrangler.tomlが設定ファイルです:
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2025-02-06"
# アカウント情報
account_id = "your_account_id"
# ルート設定
routes = [
{ pattern = "example.com/*", zone_name = "example.com" }
]
# 環境変数
[vars]
ENVIRONMENT = "production"
# KVネームスペース
[[kv_namespaces]]
binding = "MY_KV"
id = "your_kv_namespace_id"
# R2バケット
[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "my-bucket"
# D1データベース
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your_database_id"
ローカル開発ワークフロー
開発サーバーの起動
# 基本的な起動
wrangler dev
# ポート指定
wrangler dev --port 8787
# リモートモード(実際のCloudflare環境で実行)
wrangler dev --remote
# ローカルプロトコル(HTTPSでテスト)
wrangler dev --local-protocol https
Hot Reloadとデバッグ
Wrangler 3のdevサーバーは自動的にファイル変更を検出します:
// src/index.ts
export default {
async fetch(request: Request, env: Env): Promise<Response> {
console.log('Request URL:', request.url);
// デバッグ用のヘッダー出力
const headers = Object.fromEntries(request.headers);
console.log('Headers:', headers);
return new Response('Hello World!', {
headers: { 'Content-Type': 'text/plain' },
});
},
};
開発中はconsole.logがターミナルにリアルタイムで表示されます。
KV/R2のローカルエミュレーション
Wranglerは自動的にローカルストレージをエミュレートします:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// KVへの書き込み(ローカルでもエミュレート)
await env.MY_KV.put('key', 'value');
const value = await env.MY_KV.get('key');
return new Response(`Stored value: ${value}`);
},
};
.wranglerディレクトリにローカルデータが保存されます。
デプロイ戦略
基本的なデプロイ
# 本番デプロイ
wrangler deploy
# ドライラン(実際にはデプロイしない)
wrangler deploy --dry-run
# 特定の環境にデプロイ
wrangler deploy --env production
環境別設定
wrangler.tomlで複数環境を定義:
name = "my-worker"
main = "src/index.ts"
compatibility_date = "2025-02-06"
# 開発環境
[env.dev]
name = "my-worker-dev"
vars = { ENVIRONMENT = "development" }
[[env.dev.kv_namespaces]]
binding = "MY_KV"
id = "dev_kv_namespace_id"
# 本番環境
[env.production]
name = "my-worker-prod"
routes = [
{ pattern = "api.example.com/*", zone_name = "example.com" }
]
vars = { ENVIRONMENT = "production" }
[[env.production.kv_namespaces]]
binding = "MY_KV"
id = "prod_kv_namespace_id"
デプロイ時に環境を指定:
# 開発環境
wrangler deploy --env dev
# 本番環境
wrangler deploy --env production
バージョン管理とロールバック
Cloudflare Workersは自動的に以前のバージョンを保持します。ダッシュボードから簡単にロールバック可能ですが、gitタグとの連携も推奨されます:
# バージョンタグ付きデプロイ
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
wrangler deploy
# CI/CDでのデプロイ(後述)
データストア操作
KV操作
# キーの一覧表示
wrangler kv:namespace list
# 値の取得
wrangler kv:key get --binding=MY_KV "my-key"
# 値の設定
wrangler kv:key put --binding=MY_KV "my-key" "my-value"
# ファイルからの一括アップロード
wrangler kv:bulk put --binding=MY_KV data.json
# キーの削除
wrangler kv:key delete --binding=MY_KV "my-key"
JSONファイルでの一括操作例:
[
{
"key": "user:1",
"value": "{\"name\":\"Alice\",\"email\":\"alice@example.com\"}"
},
{
"key": "user:2",
"value": "{\"name\":\"Bob\",\"email\":\"bob@example.com\"}"
}
]
wrangler kv:bulk put --binding=MY_KV users.json
R2操作
# バケット一覧
wrangler r2 bucket list
# バケット作成
wrangler r2 bucket create my-bucket
# オブジェクトのアップロード
wrangler r2 object put my-bucket/file.txt --file=./local-file.txt
# オブジェクトのダウンロード
wrangler r2 object get my-bucket/file.txt --file=./downloaded-file.txt
# オブジェクトの削除
wrangler r2 object delete my-bucket/file.txt
D1データベース操作
# データベース作成
wrangler d1 create my-database
# SQLの実行
wrangler d1 execute my-database --command="CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)"
# ファイルからのSQL実行
wrangler d1 execute my-database --file=./schema.sql
# クエリの実行
wrangler d1 execute my-database --command="SELECT * FROM users"
# ローカルでのD1操作
wrangler d1 execute my-database --local --command="INSERT INTO users (name) VALUES ('Alice')"
シークレット管理
機密情報は環境変数ではなくシークレットとして管理します:
# シークレットの設定(対話的)
wrangler secret put API_KEY
# パイプ経由での設定
echo "secret-value" | wrangler secret put API_KEY
# シークレット一覧
wrangler secret list
# シークレット削除
wrangler secret delete API_KEY
# 環境別シークレット
wrangler secret put API_KEY --env production
コード内での使用:
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// シークレットはenv経由でアクセス
const apiKey = env.API_KEY;
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${apiKey}`,
},
});
return response;
},
};
ログとモニタリング
リアルタイムログ
# ログのストリーミング
wrangler tail
# 環境指定
wrangler tail --env production
# フィルタリング
wrangler tail --status error
# JSON形式で出力
wrangler tail --format json
ログ出力のベストプラクティス
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const startTime = Date.now();
try {
// 構造化ログ
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
method: request.method,
url: request.url,
userAgent: request.headers.get('user-agent'),
}));
const response = await handleRequest(request, env);
// パフォーマンスログ
const duration = Date.now() - startTime;
console.log(JSON.stringify({
type: 'performance',
duration,
status: response.status,
}));
return response;
} catch (error) {
// エラーログ
console.error(JSON.stringify({
type: 'error',
message: error.message,
stack: error.stack,
}));
return new Response('Internal Server Error', { status: 500 });
}
},
};
CI/CDパイプライン構築
GitHub Actionsでの自動デプロイ
.github/workflows/deploy.yml:
name: Deploy to Cloudflare Workers
on:
push:
branches:
- main
pull_request:
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Deploy to Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy --env production
環境別デプロイ戦略
jobs:
deploy-staging:
if: github.ref == 'refs/heads/develop'
steps:
# ...
- name: Deploy to Staging
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env staging
deploy-production:
if: github.ref == 'refs/heads/main'
steps:
# ...
- name: Deploy to Production
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
command: deploy --env production
高度な設定とベストプラクティス
TypeScript設定の最適化
tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": ["ES2022"],
"moduleResolution": "node",
"types": ["@cloudflare/workers-types"],
"resolveJsonModule": true,
"allowJs": true,
"checkJs": false,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
バンドルサイズの最適化
# wrangler.toml
[build]
command = "npm run build"
[build.upload]
format = "modules"
main = "./dist/index.js"
# 不要なファイルを除外
[site]
bucket = "./public"
exclude = ["*.map", "*.ts"]
カスタムドメイン設定
# ルートの追加
wrangler routes add "api.example.com/*" my-worker
# ルートの一覧
wrangler routes list
# ルートの削除
wrangler routes delete <route-id>
Workers Sitesでの静的ファイル配信
[site]
bucket = "./public"
entry-point = "workers-site"
import { getAssetFromKV } from '@cloudflare/kv-asset-handler';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
try {
return await getAssetFromKV(
{
request,
waitUntil: () => {},
},
{
ASSET_NAMESPACE: env.__STATIC_CONTENT,
ASSET_MANIFEST: env.__STATIC_CONTENT_MANIFEST,
}
);
} catch (e) {
return new Response('Not Found', { status: 404 });
}
},
};
トラブルシューティング
よくある問題と解決策
1. デプロイが失敗する
# 詳細なエラーログを確認
wrangler deploy --verbose
# キャッシュをクリア
rm -rf node_modules .wrangler
npm install
2. ローカル開発でKVが動作しない
# .wranglerディレクトリを削除して再起動
rm -rf .wrangler
wrangler dev
3. 認証エラー
# ログアウトして再認証
wrangler logout
wrangler login
# またはAPIトークンを確認
wrangler whoami
4. TypeScriptのビルドエラー
# 型定義のインストール
npm install -D @cloudflare/workers-types
# tsconfig.jsonでtypesを指定
デバッグテクニック
// リクエスト情報の完全なダンプ
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const debugInfo = {
url: request.url,
method: request.method,
headers: Object.fromEntries(request.headers),
cf: request.cf, // Cloudflare固有の情報
env: Object.keys(env), // バインディング一覧
};
return new Response(JSON.stringify(debugInfo, null, 2), {
headers: { 'Content-Type': 'application/json' },
});
},
};
まとめ
Wrangler CLIは、Cloudflare Workersの開発体験を大幅に向上させる強力なツールです。本記事で紹介したテクニックを活用すれば、以下のような効率的なワークフローを構築できます:
- 高速な開発サイクル: ローカル開発サーバーによる即座のフィードバック
- 環境分離: 開発・ステージング・本番の明確な分離
- 安全なデプロイ: CI/CDパイプラインによる自動テストとデプロイ
- データ管理の簡素化: KV/R2/D1の直感的な操作
- セキュリティ: シークレット管理による機密情報の保護
エッジコンピューティングの可能性を最大限に引き出すために、Wranglerを使いこなしましょう。継続的な改善とモニタリングを忘れずに、パフォーマンスとユーザー体験の向上を目指してください。