Wrangler CLI Kurulumu ve İlk Cloudflare Worker Projesi
Cloudflare Workers dünyasına adım atmak istiyorsanız, ilk durağınız Wrangler CLI olacak. Wrangler, Cloudflare’in resmi komut satırı aracı ve Workers projelerini yönetmek, deploy etmek, local’de test etmek için kullanacağınız temel silahınız. Bu yazıda sıfırdan başlayıp gerçek dünyada kullanılabilir bir Worker projesi oluşturana kadar her adımı detaylıca inceleyeceğiz.
Ön Hazırlık: Neler Lazım?
Başlamadan önce birkaç şeyin hazır olması gerekiyor. Cloudflare hesabınız yoksa workers.cloudflare.com üzerinden ücretsiz hesap açabilirsiniz. Free plan oldukça cömert: günde 100.000 istek, 10ms CPU süresi limiti. Üretim ortamları için paid plan düşünün ama öğrenme aşamasında free plan fazlasıyla yeterli.
Sistem gereksinimleri:
- Node.js: 16.17.0 veya üzeri (LTS sürüm önerilir)
- npm veya pnpm: Paket yöneticisi
- Cloudflare hesabı: API token için
- Git: Proje yönetimi için
Node.js versiyonunuzu kontrol edin:
node --version
npm --version
Eğer Node.js yönetimi için nvm kullanıyorsanız (ki kullanmanızı şiddetle tavsiye ederim), LTS sürümü şu şekilde kurabilirsiniz:
nvm install --lts
nvm use --lts
Wrangler CLI Kurulumu
Wrangler’ı global olarak kurmak yerine proje bazlı kullanmak daha temiz bir yaklaşım. Ama önce global kurulumla tanışalım:
npm install -g wrangler
Kurulum tamamlandıktan sonra versiyonu doğrulayın:
wrangler --version
Wrangler 3.x sürümü şu an aktif geliştirilen dal. Eğer eski bir kurulumunuz varsa güncellemeyi unutmayın:
npm update -g wrangler
Cloudflare Hesabıyla Kimlik Doğrulama
Wrangler’ı kullanabilmek için Cloudflare hesabınıza bağlamanız gerekiyor. İki yöntem var:
Yöntem 1: OAuth ile Login (Önerilen)
wrangler login
Bu komut tarayıcıyı açacak ve Cloudflare’in OAuth sayfasına yönlendirecek. İzinleri onayladıktan sonra terminal otomatik olarak authenticate olmuş olacak. Token bilgileri ~/.config/.wrangler/config/default.toml dosyasına kaydediliyor.
Yöntem 2: API Token ile Authentication
CI/CD pipeline’larında veya headless sunucularda OAuth kullanamıyorsunuz. Bu durumda API token yaklaşımı gerekiyor:
Cloudflare Dashboard > My Profile > API Tokens > Create Token yolunu izleyin. “Edit Cloudflare Workers” template’ini seçin, zone ayarlarını düzenleyin ve token’ı oluşturun.
export CLOUDFLARE_API_TOKEN="your_api_token_here"
CI/CD ortamlarında bu environment variable’ı pipeline secret’larına eklemeyi unutmayın.
Kimlik doğrulamayı test etmek için:
wrangler whoami
Account bilgilerinizi görüyorsanız her şey yolunda demektir.
İlk Worker Projesi Oluşturma
Wrangler ile proje oluşturmak son derece basit. create komutu sizi interaktif bir wizard’a yönlendiriyor:
npm create cloudflare@latest my-first-worker
Alternatif olarak doğrudan Wrangler ile de oluşturabilirsiniz:
wrangler init my-first-worker
Wizard size birkaç soru soracak:
- Proje tipi (Worker, Worker with Assets, Pages vb.)
- TypeScript kullanmak istiyor musunuz?
- Test framework tercihinde bulunmak ister misiniz?
Şimdilik “Hello World” Worker seçeneğiyle ve TypeScript ile devam edelim. Proje oluşturulduktan sonra dizine girin:
cd my-first-worker
ls -la
Proje yapısına bakalım:
- wrangler.toml: Proje konfigürasyonu, en kritik dosya
- src/index.ts: Worker kodunuzun bulunduğu ana dosya
- package.json: Bağımlılıklar ve scriptler
- tsconfig.json: TypeScript konfigürasyonu
wrangler.toml Dosyasını Anlamak
Bu dosya Worker’ınızın beyni. Açıp inceleyelim:
cat wrangler.toml
Tipik bir wrangler.toml şu şekilde görünür:
# wrangler.toml içeriği (bu bash bloğu config gösterimi için)
name = "my-first-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[vars]
MY_VARIABLE = "production_value"
[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-namespace-id"
Önemli alanlar:
- name: Worker’ınızın Cloudflare’deki adı, deployment URL’ini belirliyor
- main: Entry point dosyası
- compatibility_date: Cloudflare runtime’ının hangi versiyonunu kullanacağınızı belirliyor, bunu güncel tutun
- vars: Environment variable’lar
İlk Worker Kodunu Yazalım
src/index.ts dosyasını açın. Varsayılan içerik şu şekilde:
# TypeScript Worker kodu (index.ts)
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
return new Response('Hello World!');
},
};
Bu çok basit ama Workers’ın temel konseptini gösteriyor. Her Worker bir fetch event handler’ı export ediyor. Request geldiğinde bu fonksiyon çağrılıyor ve Response dönüyor.
Şimdi daha gerçekçi bir örnek yazalım. Diyelim ki bir API routing yapıyoruz:
# Gelişmiş Worker örneği
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const path = url.pathname;
// CORS headers
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Content-Type': 'application/json',
};
// OPTIONS preflight
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
// Route handling
if (path === '/api/health') {
return new Response(
JSON.stringify({ status: 'ok', timestamp: Date.now() }),
{ headers: corsHeaders }
);
}
if (path === '/api/info') {
const info = {
region: request.cf?.colo || 'unknown',
country: request.cf?.country || 'unknown',
city: request.cf?.city || 'unknown',
userAgent: request.headers.get('User-Agent'),
};
return new Response(JSON.stringify(info), { headers: corsHeaders });
}
return new Response(
JSON.stringify({ error: 'Not Found' }),
{ status: 404, headers: corsHeaders }
);
},
};
Bu örnekte dikkat çekici birkaç şey var. request.cf objesi Cloudflare’e özgü metadata içeriyor: kullanıcının hangi ülkeden bağlandığı, hangi Cloudflare datacenter’ı kullandığı (colo) gibi bilgiler. Bu bilgileri ücretsiz olarak alıyorsunuz, ayrıca GeoIP servisi satın almanıza gerek yok.
Local Development: Wrangler Dev
Local’de test etmek için:
wrangler dev
Bu komut local bir server başlatıyor, genellikle http://localhost:8787 adresinde. Hot reload özelliğiyle dosyada değişiklik yaptığınızda otomatik olarak güncelleniyor.
Farklı port belirtmek için:
wrangler dev --port 9000
Remote modda çalıştırmak (gerçek Cloudflare edge’inde test):
wrangler dev --remote
Remote mod özellikle KV, D1 database gibi Cloudflare servislerini kullanan Worker’ları test ederken işe yarıyor çünkü local emülatörün bazı limitleri var.
Başka terminal açıp API’yi test edelim:
# Health check
curl http://localhost:8787/api/health
# Lokasyon bilgisi (local'de CF metadata boş gelir)
curl http://localhost:8787/api/info
# 404 testi
curl http://localhost:8787/api/nonexistent
KV Storage Entegrasyonu
Gerçek dünya uygulamalarında veri saklamanız gerekiyor. Cloudflare KV (Key-Value) storage bu iş için biçilmiş kaftan. Önce KV namespace oluşturun:
# Production namespace
wrangler kv namespace create "USER_DATA"
# Preview namespace (local dev için)
wrangler kv namespace create "USER_DATA" --preview
Bu komutlar size namespace ID’leri verecek. Bunları wrangler.toml‘a ekleyin:
# wrangler.toml'a eklenecek konfigürasyon
[[kv_namespaces]]
binding = "USER_DATA"
id = "abc123production"
preview_id = "abc123preview"
Şimdi Worker kodunu KV kullanacak şekilde güncelleyelim:
# KV kullanan Worker örneği
interface Env {
USER_DATA: KVNamespace;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const path = url.pathname;
if (request.method === 'POST' && path === '/api/user') {
const body = await request.json() as { name: string; email: string };
const userId = crypto.randomUUID();
await env.USER_DATA.put(userId, JSON.stringify(body), {
expirationTtl: 86400, // 24 saat sonra otomatik sil
});
return new Response(
JSON.stringify({ id: userId, message: 'User created' }),
{
status: 201,
headers: { 'Content-Type': 'application/json' }
}
);
}
if (request.method === 'GET' && path.startsWith('/api/user/')) {
const userId = path.replace('/api/user/', '');
const userData = await env.USER_DATA.get(userId);
if (!userData) {
return new Response(
JSON.stringify({ error: 'User not found' }),
{ status: 404, headers: { 'Content-Type': 'application/json' } }
);
}
return new Response(userData, {
headers: { 'Content-Type': 'application/json' }
});
}
return new Response('Not Found', { status: 404 });
},
};
KV’yi komut satırından test etmek de mümkün:
# KV'ye değer yaz
wrangler kv key put --namespace-id="abc123preview" "test-key" "test-value"
# KV'den değer oku
wrangler kv key get --namespace-id="abc123preview" "test-key"
# Tüm keyleri listele
wrangler kv key list --namespace-id="abc123preview"
Environment Variables ve Secrets
Hassas bilgileri (API key, database password vb.) wrangler.toml’a yazmayın. Bunun için Cloudflare Secrets kullanın:
# Secret ekle (değeri terminal prompt'tan gireceksiniz)
wrangler secret put DATABASE_PASSWORD
# Mevcut secretları listele
wrangler secret list
# Secret sil
wrangler secret delete DATABASE_PASSWORD
Normal environment variable’lar için wrangler.toml:
# Environment variables konfigürasyonu
[vars]
API_BASE_URL = "https://api.example.com"
APP_ENV = "production"
MAX_REQUESTS = "1000"
Worker kodunda bunlara env.DATABASE_PASSWORD, env.API_BASE_URL şeklinde erişiyorsunuz.
Deployment
Local testleri başarılı olduktan sonra deploy zamanı:
wrangler deploy
Deployment tamamlandığında Worker URL’nizi göreceksiniz: https://my-first-worker.your-subdomain.workers.dev
Staging ortamı için farklı environment’lar kullanabilirsiniz. wrangler.toml‘a staging konfigürasyonu ekleyin:
# Staging environment konfigürasyonu
[env.staging]
name = "my-first-worker-staging"
vars = { APP_ENV = "staging" }
[[env.staging.kv_namespaces]]
binding = "USER_DATA"
id = "staging-kv-namespace-id"
Staging’e deploy etmek için:
wrangler deploy --env staging
Deploy geçmişini görmek ve rollback yapmak için:
# Deploy listesi
wrangler deployments list
# Belirli versiyona rollback
wrangler rollback --deployment-id="deployment-id-here"
Gerçek Dünya Senaryosu: Rate Limiting Middleware
İşte Workers’ın gerçekten parlayan bir kullanım senaryosu. KV storage kullanarak basit bir rate limiter yazalım:
# Rate limiting Worker implementasyonu
interface Env {
RATE_LIMIT: KVNamespace;
}
async function checkRateLimit(
ip: string,
env: Env,
limit: number = 10,
windowSeconds: number = 60
): Promise<{ allowed: boolean; remaining: number; resetAt: number }> {
const key = `rl:${ip}`;
const now = Math.floor(Date.now() / 1000);
const windowStart = now - windowSeconds;
const current = await env.RATE_LIMIT.get(key, { type: 'json' }) as
{ count: number; windowStart: number } | null;
if (!current || current.windowStart < windowStart) {
await env.RATE_LIMIT.put(key, JSON.stringify({ count: 1, windowStart: now }), {
expirationTtl: windowSeconds,
});
return { allowed: true, remaining: limit - 1, resetAt: now + windowSeconds };
}
if (current.count >= limit) {
return {
allowed: false,
remaining: 0,
resetAt: current.windowStart + windowSeconds
};
}
await env.RATE_LIMIT.put(key, JSON.stringify({
count: current.count + 1,
windowStart: current.windowStart
}), { expirationTtl: windowSeconds });
return {
allowed: true,
remaining: limit - current.count - 1,
resetAt: current.windowStart + windowSeconds
};
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const ip = request.headers.get('CF-Connecting-IP') || '0.0.0.0';
const { allowed, remaining, resetAt } = await checkRateLimit(ip, env);
const rateLimitHeaders = {
'X-RateLimit-Limit': '10',
'X-RateLimit-Remaining': remaining.toString(),
'X-RateLimit-Reset': resetAt.toString(),
'Content-Type': 'application/json',
};
if (!allowed) {
return new Response(
JSON.stringify({ error: 'Too Many Requests' }),
{ status: 429, headers: rateLimitHeaders }
);
}
// Asıl iş mantığınız burada
return new Response(
JSON.stringify({ message: 'Request processed', remainingRequests: remaining }),
{ headers: rateLimitHeaders }
);
},
};
Bu rate limiter edge’de çalışıyor yani her Cloudflare datacenter’ında ayrı ayrı limit sayıyor. Global rate limiting için Durable Objects’e bakmanız gerekiyor ama basit senaryolar için bu yaklaşım gayet iyi.
Log ve Monitoring
Deploy sonrası logları takip etmek için:
# Real-time log streaming
wrangler tail
# Belirli bir Worker için
wrangler tail my-first-worker
# JSON formatında loglar
wrangler tail --format json
# Sadece hataları göster
wrangler tail --status error
wrangler tail komutu production ortamındaki gerçek trafiği canlı olarak gösteriyor. Debug için son derece kullanışlı.
Worker kodunuzda console.log kullandığınızda bunlar otomatik olarak bu stream’e geliyor:
# Worker içinde loglama
console.log('Request received:', request.url);
console.error('Something went wrong:', error.message);
Sık Karşılaşılan Sorunlar ve Çözümleri
Wrangler login sonrası token hatası alıyorum:
Token dosyasını silip tekrar login olmayı deneyin:
rm -rf ~/.config/.wrangler
wrangler login
“Workers.dev subdomain not configured” hatası:
Dashboard’da Workers & Pages > Your subdomain kısmından subdomain’inizi ayarlayın. Bir kez yapıldıktan sonra tüm Worker’larınız bu subdomain altında çalışır.
CPU time limit aşımı:
Free plan’da 10ms CPU limiti var. Paid plan’da bu 50ms’ye çıkıyor. Ağır hesaplama işlemleri için Workers uygun değil, bu işleri origin server’a bırakın. Workers daha çok routing, authentication, edge caching, request/response manipulation için ideal.
KV namespace bulunamıyor:
Preview namespace ID’sini production ID’siyle karıştırmak çok yaygın bir hata. wrangler dev için preview_id, deploy için id kullanıldığını unutmayın.
Sonuç
Wrangler CLI ve Cloudflare Workers ikilisi, edge computing dünyasına giriş için mükemmel bir başlangıç noktası. Kurulum süreci oldukça pürüzsüz, local development deneyimi wrangler dev sayesinde gerçekten keyifli ve deployment tek komutla halloluyor.
Bu yazıda temel kurulumdan başlayıp KV storage entegrasyonu, environment management, gerçek dünya rate limiting örneği ve monitoring konularına kadar uzandık. Workers’ın asıl gücü ise henüz değinmediğimiz konularda saklı: Durable Objects ile stateful uygulamalar, D1 ile edge-side SQL database, R2 ile object storage ve WebAssembly modülü yükleme gibi özellikler.
Edge computing’in getirdiği en büyük avantaj gecikme sürelerinin dramatik biçimde düşmesi. Kullanıcıya yakın, dünyanın 300’den fazla noktasında çalışan bir uygulama düşünün ve bunun için tek bir sunucu yönetmek zorunda kalmayın. Workers tam da bunu sağlıyor. Sysadmin perspektifinden bakıldığında, yönetilecek sunucu yok, patch yok, kapasitelere karar vermek yok. Odağınız tamamen uygulama koduna kayıyor ki bu bence en büyük kazanım.
