TL;DR — Résumé Rapide
Cloudflare Workers exécute JavaScript en périphérie avec des isolats V8. Déployez votre premier Worker avec Wrangler, KV, secrets et CI/CD via GitHub Actions.
Cloudflare Workers apporte le calcul serverless à la périphérie — votre code s’exécute dans des data centers répartis dans plus de 300 villes à travers le monde, à quelques millisecondes de vos utilisateurs, sans aucun provisionnement ou mise à l’échelle de serveurs. Construit sur des isolats V8 (le même moteur qui propulse Chrome et Node.js), Workers atteint des temps de démarrage à froid inférieurs à 1 milliseconde, étant dramatiquement plus rapide que les fonctions serverless traditionnelles basées sur des conteneurs. Dans ce guide, vous passerez de zéro à un Worker entièrement déployé en production avec stockage KV, secrets chiffrés, domaines personnalisés et un pipeline de déploiement automatisé avec GitHub Actions.
Prérequis
- Node.js 18+ installé localement
- Un compte Cloudflare (le niveau gratuit fonctionne pour tout dans ce guide)
- Familiarité de base avec JavaScript ou TypeScript
- Un domaine enregistré ajouté à Cloudflare (requis uniquement pour la section domaine personnalisé)
- npm ou pnpm comme gestionnaire de paquets
Créer votre Premier Worker
Installez Wrangler, la CLI officielle de Cloudflare, globalement :
npm install -g wrangler
wrangler login
La commande wrangler login ouvre une fenêtre de navigateur et vous demande d’autoriser Wrangler à accéder à votre compte Cloudflare. Après l’autorisation, les identifiants sont stockés dans ~/.wrangler/config/default.toml.
Créez un nouveau projet :
wrangler init my-api-worker
cd my-api-worker
Wrangler présente quelques questions — choisissez TypeScript et le template “Hello World” Worker. La structure du répertoire résultante est :
my-api-worker/
src/
index.ts ← votre code Worker
wrangler.toml ← configuration du projet
package.json
tsconfig.json
Comprendre wrangler.toml
Le fichier wrangler.toml est le manifeste du projet. Une configuration minimale ressemble à :
name = "my-api-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"
Champs clés :
| Champ | Rôle |
|---|---|
name | Nom du Worker affiché dans le tableau de bord |
main | Fichier d’entrée résolu par Wrangler |
compatibility_date | Fixe le comportement de l’API runtime à une date spécifique |
routes | Mappe les patterns d’URL vers ce Worker |
[[kv_namespaces]] | Lie les namespaces KV comme variables d’environnement |
[vars] | Variables d’environnement en texte brut |
La compatibility_date est importante — Cloudflare introduit occasionnellement des changements incompatibles dans les APIs Worker, et cette date fixe quel ensemble d’APIs votre Worker voit.
Écrire le Worker
Le point d’entrée du Worker exporte un objet par défaut avec un handler fetch. Chaque requête HTTP entrante appelle ce handler :
export interface Env {
MY_KV: KVNamespace;
API_SECRET: string;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
// Route : retourner du JSON
if (url.pathname === '/api/status') {
return Response.json({ status: 'ok', region: request.cf?.colo });
}
// Route : retourner du HTML
if (url.pathname === '/') {
return new Response(
`<h1>Bonjour depuis la périphérie !</h1>`,
{ headers: { 'Content-Type': 'text/html;charset=UTF-8' } }
);
}
return new Response('Non Trouvé', { status: 404 });
}
};
Patterns de Request et Response
Workers utilise l’API Fetch standard — Request, Response et Headers sont identiques aux APIs du navigateur. Cela signifie que le code que vous écrivez pour Workers est largement portable.
Retourner du JSON est idiomatique avec Response.json() :
return Response.json({ items: ['a', 'b', 'c'] }, {
headers: { 'Cache-Control': 'public, max-age=60' }
});
Rediriger une requête :
return Response.redirect('https://example.com/nouveau-chemin', 301);
Modifier une réponse proxiée (le pattern “transform”) :
const upstream = await fetch(request);
const body = await upstream.text();
return new Response(body.replace('ancien texte', 'nouveau texte'), upstream);
Développement Local
Démarrez le serveur de développement local :
wrangler dev
Wrangler démarre un serveur local sur http://localhost:8787 qui émule le runtime Cloudflare incluant KV, Durable Objects, R2 et l’objet de métadonnées request.cf. Le rechargement à chaud se déclenche automatiquement lors des changements de fichiers.
Pour tester contre l’infrastructure réelle de Cloudflare :
wrangler dev --remote
Inspectez le trafic en temps réel avec le log tail intégré dans un second terminal :
wrangler tail
Déployer en Production
Déployez avec une seule commande :
wrangler deploy
Wrangler compile votre TypeScript, empaquète les dépendances et télécharge le Worker sur le réseau Cloudflare. Le déploiement se propage mondialement en secondes. La sortie inclut l’URL workers.dev :
Published my-api-worker (2.45 sec)
https://my-api-worker.votre-sous-domaine.workers.dev
Connecter un Domaine Personnalisé
Ajoutez un bloc routes dans wrangler.toml pour router les requêtes de votre domaine proxié par Cloudflare vers le Worker :
[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"
Alternativement, utilisez la fonctionnalité Custom Domains :
[[routes]]
pattern = "api.example.com"
custom_domain = true
Variables d’Environnement et Secrets
Variables Simples
La configuration non sensible vit dans wrangler.toml :
[vars]
ENVIRONMENT = "production"
MAX_RETRIES = "3"
Secrets Chiffrés
Les secrets sont chiffrés au repos et ne sont jamais visibles après le téléchargement. Ajoutez-les via CLI :
wrangler secret put API_KEY
Wrangler vous demande de saisir la valeur de manière interactive. Listez les secrets existants :
wrangler secret list
Dans le Worker, les secrets apparaissent comme env.API_KEY — indiscernables des variables simples à l’exécution mais stockés chiffrés dans le coffre de Cloudflare.
Stockage KV
KV (Workers KV) est un stockage clé-valeur distribué mondialement avec cohérence éventuelle. Il excelle pour stocker des configurations, sessions utilisateurs, réponses d’API en cache et feature flags.
Créez un namespace KV :
wrangler kv namespace create CACHE
Ajoutez le binding à wrangler.toml :
[[kv_namespaces]]
binding = "CACHE"
id = "abc123def456..."
Écrivez et lisez depuis KV dans le Worker :
// Écrire (avec TTL optionnel en secondes)
await env.CACHE.put('utilisateur:123', JSON.stringify(donneesUtil), { expirationTtl: 3600 });
// Lire
const raw = await env.CACHE.get('utilisateur:123');
const utilisateur = raw ? JSON.parse(raw) : null;
// Supprimer
await env.CACHE.delete('utilisateur:123');
Comparaison
| Fonctionnalité | Cloudflare Workers | AWS Lambda@Edge | Deno Deploy |
|---|---|---|---|
| Runtime | Isolats V8 | Conteneur Node.js | Isolats V8 |
| Démarrage à froid | < 1 ms | 100–500 ms | ~50 ms |
| PoP mondiaux | 300+ | ~4 régions CloudFront | 35 régions |
| Niveau gratuit | 100k req/jour | Paiement par requête | 100k req/jour |
| Temps CPU max. | 50 ms (gratuit) / 30 s (payant) | 30 s | 50 ms |
| Stockage | KV, R2, D1, Durable Objects | DynamoDB (séparé) | Deno KV |
| TypeScript | Natif (intégré) | Via étape de build | Natif |
| Prix (au-delà du gratuit) | 0,50$/million requêtes | ~0,60$/million + Lambda | 0,50$/million requêtes |
Workers gagne sur le démarrage à froid et la distribution mondiale. Lambda@Edge est le bon choix si vous êtes déjà profondément investi dans l’écosystème AWS. Deno Deploy est une bonne alternative si vous voulez le modèle de permissions de Deno.
Scénario Réel : Worker Proxy d’API
Vous avez une API tierce qui ne supporte pas CORS, nécessite une clé API que vous ne pouvez pas exposer au navigateur, et répond avec des données que vous souhaitez mettre en cache et transformer. Un Cloudflare Worker est la solution parfaite.
export interface Env {
UPSTREAM_API_KEY: string;
CACHE: KVNamespace;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const upstreamUrl = `https://api.tiers.com${url.pathname}${url.search}`;
const cacheKey = upstreamUrl;
// Vérifier le cache KV d'abord
const cached = await env.CACHE.get(cacheKey);
if (cached) {
return Response.json(JSON.parse(cached), {
headers: { 'X-Cache': 'HIT', 'Access-Control-Allow-Origin': '*' }
});
}
// Récupérer depuis l'upstream avec la clé secrète
const upstream = await fetch(upstreamUrl, {
headers: { 'Authorization': `Bearer ${env.UPSTREAM_API_KEY}` }
});
if (!upstream.ok) {
return new Response('Erreur upstream', { status: upstream.status });
}
const data = await upstream.json();
// Mettre en cache la réponse pour 5 minutes
ctx.waitUntil(env.CACHE.put(cacheKey, JSON.stringify(data), { expirationTtl: 300 }));
return Response.json(data, {
headers: { 'X-Cache': 'MISS', 'Access-Control-Allow-Origin': '*' }
});
}
};
Ce Worker garde la clé API côté serveur, ajoute des en-têtes CORS manquants, et sert des réponses en cache depuis les emplacements edge les plus proches de chaque utilisateur.
CI/CD avec GitHub Actions
Automatisez les déploiements à chaque push vers main :
# .github/workflows/deploy.yml
name: Deploy Worker
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v4
- name: Configurer Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Installer les dépendances
run: npm ci
- name: Déployer sur Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Ajoutez CF_API_TOKEN et CLOUDFLARE_ACCOUNT_ID comme secrets du dépôt dans GitHub. Créez le token API dans le tableau de bord Cloudflare sous Profil → Tokens API → Créer un Token en utilisant le modèle “Edit Cloudflare Workers”.
Pièges et Cas Particuliers
Limite de temps CPU — Le plan gratuit autorise 10 ms de temps CPU par requête. Le plan Workers Paid augmente cela à 30 secondes. Un travail intensif en CPU peut atteindre cette limite ; déchargez les calculs lourds vers une file d’attente ou utilisez des Durable Objects.
Limites de sous-requêtes — Chaque invocation de Worker peut effectuer jusqu’à 50 appels fetch() sortants sur le plan gratuit (1000 sur le plan payant).
Date de compatibilité et changements incompatibles — Lors de la mise à jour de compatibility_date, examinez le journal des modifications des flags de compatibilité.
Limites de taille — Les scripts Worker sont limités à 1 Mo après compression (10 Mo sur le plan payant). Les grandes dépendances npm peuvent dépasser cette limite ; utilisez le tree shaking.
Pas d’accès au système de fichiers — Les Workers n’ont pas d’E/S disque. Toute persistance doit passer par KV, R2, D1 ou Durable Objects.
waitUntil pour le travail en arrière-plan — Utilisez ctx.waitUntil(promise) pour le travail devant se terminer après l’envoi de la réponse (comme les écritures en cache).
Résolution de Problèmes
Error: Script startup exceeded CPU time limit — Votre Worker effectue un travail coûteux lors de l’initialisation du module. Déplacez les opérations coûteuses à l’intérieur du handler ou utilisez une initialisation lazy.
TypeError: Cannot read properties of undefined (reading 'get') — Un binding KV ou autre binding est absent de wrangler.toml, ou vous accédez à env.MON_BINDING avant que le binding ne soit configuré.
wrangler deploy échoue avec “Authentication error” — Votre session Wrangler a expiré. Exécutez wrangler login à nouveau ou définissez la variable d’environnement CLOUDFLARE_API_TOKEN.
Erreurs CORS dans le navigateur — La réponse du Worker manque Access-Control-Allow-Origin. Ajoutez l’en-tête dans votre constructeur Response. Gérez également la requête de preflight OPTIONS séparément.
Le domaine personnalisé ne route pas vers le Worker — Assurez-vous que le domaine est proxié par Cloudflare (nuage orange dans les paramètres DNS), que le pattern de route dans wrangler.toml utilise le joker /* si nécessaire, et que vous avez redéployé après avoir modifié wrangler.toml.
Résumé
- Les Cloudflare Workers sont des fonctions serverless basées sur des isolats V8 qui s’exécutent à la périphérie avec des démarrages à froid inférieurs à la milliseconde et une distribution mondiale
- Installez Wrangler avec
npm install -g wrangler, créez le squelette avecwrangler initet testez localement avecwrangler dev - Le fichier
wrangler.tomlcontrôle le nom du Worker, le point d’entrée, la date de compatibilité, les routes et tous les bindings de ressources - Utilisez
wrangler secret putpour les valeurs sensibles et[vars]danswrangler.tomlpour la configuration non sensible - Les namespaces KV fournissent un stockage clé-valeur distribué mondialement, accessible via
env.BINDING.get/put/delete - Workers surpasse Lambda@Edge sur le démarrage à froid et la portée mondiale ; Lambda@Edge est préférable pour une intégration profonde dans l’écosystème AWS
- L’Action
wrangler-actionde GitHub fournit un CI/CD clé en main ; limitez votre token API aux seules permissions Workers - Surveillez les limites de temps CPU, les plafonds de sous-requêtes et le plafond de 1 Mo de taille de script sur le plan gratuit