ITSkillsCenter
Blog

Cloudflare Workers : edge computing

9 min de lecture

Ce que vous saurez faire à la fin

  1. Déployer un script JavaScript ou TypeScript en bordure du réseau Cloudflare (300+ datacenters dont Lagos et Le Cap).
  2. Construire une API ultra-rapide avec moins de 10 ms de latence depuis Dakar.
  3. Stocker des données via Workers KV, R2 (compatible S3) ou D1 (SQLite serverless).
  4. Mettre en place un domaine personnalisé .sn avec SSL automatique.
  5. Maîtriser le coût : 100 000 requêtes/jour gratuites, puis 0,30 USD (180 FCFA) par million de requêtes au-delà.

Durée : 4h. Pré-requis : Compte Cloudflare gratuit (puis upgrade Workers Paid à 5 USD/mois si besoin de KV/D1 illimités), Node.js 20+, npm, terminal, un nom de domaine déjà géré dans Cloudflare DNS, connaissance de base en JavaScript moderne (async/await, fetch).

Étape 1 — Comprendre l’edge computing

L’edge computing exécute votre code au plus près de l’utilisateur. Quand un visiteur de Dakar appelle votre API, la requête n’a pas besoin de traverser l’Atlantique vers AWS Virginie : elle est traitée à Lagos ou Casablanca, à 30-50 ms de Dakar contre 180-250 ms pour un serveur européen.

Cloudflare Workers utilise V8 isolates (le même moteur que Chrome) au lieu de containers Docker. Résultat : démarrage à froid de moins de 5 ms (contre 800 ms pour Lambda), et facturation par requête sans coût de bande passante sortante. Pour une PME africaine servant majoritairement un public africain, c’est un game-changer.

Étape 2 — Installer Wrangler CLI

# Wrangler est le CLI officiel Cloudflare Workers
npm install -g wrangler

# Vérifier
wrangler --version
# wrangler 3.50.0

# S'authentifier (ouvre un navigateur)
wrangler login

# Vérifier le compte
wrangler whoami

Étape 3 — Initialiser un projet Worker

# Création interactive
wrangler init api-pme-dakar

# Choix recommandés :
# What type of application : "Hello World" Worker
# Language : TypeScript
# Use git : Yes
# Deploy : No (on déploiera plus tard)

cd api-pme-dakar

# Structure générée :
# api-pme-dakar/
#   src/
#     index.ts
#   wrangler.toml      # configuration Worker
#   package.json
#   tsconfig.json

Étape 4 — Écrire le premier Worker

// src/index.ts
export interface Env {
  // Bindings ajoutés ici (KV, R2, D1, secrets)
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    const country = request.cf?.country || 'Inconnu';
    const colo = request.cf?.colo || '?';

    if (url.pathname === '/') {
      return new Response(JSON.stringify({
        message: 'API PME Dakar sur Cloudflare Workers',
        edge: colo,
        pays_visiteur: country,
        timestamp: new Date().toISOString()
      }), {
        headers: { 'Content-Type': 'application/json' }
      });
    }

    return new Response('Not Found', { status: 404 });
  }
};

Étape 5 — Configurer wrangler.toml

name = "api-pme-dakar"
main = "src/index.ts"
compatibility_date = "2026-04-01"
compatibility_flags = ["nodejs_compat"]

# Limites par défaut (Free plan)
# - 100 000 requêtes/jour
# - 10 ms CPU/requête
# - 128 MB mémoire

[observability]
enabled = true

[[routes]]
pattern = "api.monentreprise.sn/*"
zone_name = "monentreprise.sn"

[env.preview]
name = "api-pme-dakar-preview"

Étape 6 — Tester localement

# Lancer en local avec un environnement Workers fidèle
wrangler dev

# Le Worker tourne sur http://localhost:8787
curl http://localhost:8787/

# Mode tunnel (test depuis un autre appareil sur internet)
wrangler dev --remote

Étape 7 — Déployer sur l’edge

# Premier déploiement
wrangler deploy

# Sortie attendue :
# Total Upload: 5.2 KiB / gzip: 1.8 KiB
# Uploaded api-pme-dakar (0.85 sec)
# Published api-pme-dakar (5.21 sec)
#   https://api-pme-dakar.votre-compte.workers.dev

# Tester immédiatement
curl https://api-pme-dakar.votre-compte.workers.dev/

# Vérifier depuis quel datacenter on est servi
curl -I https://api-pme-dakar.votre-compte.workers.dev/ | grep cf-ray
# cf-ray: 8a1b2c3d4e5f6789-LOS  (Lagos !)

Étape 8 — Créer un namespace KV pour stocker des données

Workers KV est un magasin clé-valeur globalement répliqué, parfait pour des configs, sessions, cache de réponses, ou petits objets JSON.

# Créer un namespace
wrangler kv namespace create "CLIENTS"

# Sortie :
# binding = "CLIENTS"
# id = "abcdef1234567890"

# Ajouter au wrangler.toml
# [[kv_namespaces]]
# binding = "CLIENTS"
# id = "abcdef1234567890"

# Insérer une donnée depuis le terminal
wrangler kv key put --binding=CLIENTS \
    "client:001" \
    '{"nom":"Diop SARL","ville":"Dakar","tel":"+221771234567"}'

# Lire
wrangler kv key get --binding=CLIENTS "client:001"

Étape 9 — Implémenter une API REST avec KV

// src/index.ts
export interface Env {
  CLIENTS: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);
    const json = (data: unknown, status = 200) => new Response(
      JSON.stringify(data),
      { status, headers: { 'Content-Type': 'application/json' } }
    );

    // GET /clients/:id
    if (request.method === 'GET' && url.pathname.startsWith('/clients/')) {
      const id = url.pathname.split('/')[2];
      const value = await env.CLIENTS.get(`client:${id}`, 'json');
      return value ? json(value) : json({ error: 'Introuvable' }, 404);
    }

    // POST /clients
    if (request.method === 'POST' && url.pathname === '/clients') {
      const body = await request.json<{ nom: string; ville: string; tel: string }>();
      const id = crypto.randomUUID();
      await env.CLIENTS.put(`client:${id}`, JSON.stringify({ id, ...body }));
      return json({ id, ...body }, 201);
    }

    // GET /clients (liste)
    if (request.method === 'GET' && url.pathname === '/clients') {
      const list = await env.CLIENTS.list({ prefix: 'client:' });
      const items = await Promise.all(
        list.keys.map(k => env.CLIENTS.get(k.name, 'json'))
      );
      return json(items);
    }

    return json({ error: 'Route inconnue' }, 404);
  }
};

Étape 10 — Utiliser D1 pour des requêtes SQL

D1 est une base SQLite serverless, idéale quand vous avez besoin de relations et de requêtes complexes.

# Créer une base D1
wrangler d1 create pme-database

# Ajouter au wrangler.toml :
# [[d1_databases]]
# binding = "DB"
# database_name = "pme-database"
# database_id = "abc-def-123"

# Créer le schéma
cat > schema.sql <<'EOF'
CREATE TABLE commandes (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  client_id TEXT NOT NULL,
  montant_xof INTEGER NOT NULL,
  statut TEXT DEFAULT 'en_attente',
  cree_le DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_client ON commandes(client_id);
EOF

# Appliquer le schéma en production
wrangler d1 execute pme-database --file=./schema.sql --remote

# Tester une requête
wrangler d1 execute pme-database --remote \
    --command="SELECT count(*) FROM commandes"

Étape 11 — Stocker des fichiers dans R2 (compatible S3)

R2 est l’équivalent de S3 mais sans frais de bande passante sortante (zéro). Parfait pour servir des images produit, factures PDF, sauvegardes.

# Créer un bucket R2
wrangler r2 bucket create pme-fichiers

# Ajouter au wrangler.toml :
# [[r2_buckets]]
# binding = "FICHIERS"
# bucket_name = "pme-fichiers"

# Uploader un fichier
wrangler r2 object put pme-fichiers/logo.png --file=./logo.png

# Lister
wrangler r2 object get pme-fichiers/logo.png
// Servir un fichier R2 depuis le Worker
if (url.pathname.startsWith('/files/')) {
  const key = url.pathname.replace('/files/', '');
  const obj = await env.FICHIERS.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',
      'Cache-Control': 'public, max-age=86400'
    }
  });
}

Étape 12 — Configurer un domaine personnalisé

Si votre domaine est déjà chez Cloudflare DNS, le mapping est instantané. Sinon, transférez d’abord les nameservers.

# Déclarer la route dans wrangler.toml puis déployer
# [[routes]]
# pattern = "api.monentreprise.sn/*"
# zone_name = "monentreprise.sn"

wrangler deploy

# Cloudflare ajoute automatiquement un enregistrement AAAA/A
# pour api.monentreprise.sn pointant vers leurs IPs anycast
# Le certificat SSL Universal est généré en moins de 60 s

Étape 13 — Stocker des secrets de manière sécurisée

# Ajouter un secret (interactif, valeur masquée)
wrangler secret put API_KEY
# Enter the value : ********

wrangler secret put STRIPE_KEY
wrangler secret put ORANGE_MONEY_TOKEN

# Lister les secrets (sans afficher les valeurs)
wrangler secret list

# Utilisation dans le code
# const key = env.API_KEY;
// Vérifier l'API key d'entrée
if (request.headers.get('x-api-key') !== env.API_KEY) {
  return new Response('Non autorisé', { status: 401 });
}

Étape 14 — Surveiller, débugger et estimer les coûts

# Tail des logs en temps réel
wrangler tail

# Filtrer par status code
wrangler tail --status error

# Métriques dans le dashboard Cloudflare :
# - Requests / day
# - CPU time (P50, P95, P99)
# - Sub-requests
# - KV reads / writes
# - Errors
Plan Requêtes incluses Au-delà KV / D1 / R2
Free 100 000/jour Bloqué (HTTP 429) 1 Go KV gratuit, R2 10 Go gratuits
Workers Paid (5 USD ~ 3 000 FCFA/mois) 10 millions/mois inclus 0,30 USD / million KV/D1/R2 illimités avec petits frais à l’usage

Pour une PME servant 200 000 requêtes/jour (catalogue produits, API mobile, formulaires), le plan Paid à 3 000 FCFA/mois suffit largement. Pas de coût caché de bande passante grâce au modèle Cloudflare.

Erreurs courantes à éviter

  • Limite CPU 10 ms dépassée : un calcul lourd (boucle longue, parsing énorme) sera tué. Optimisez ou passez sur Workers Paid (50 ms inclus, jusqu’à 30 s en mode unbound).
  • Requêtes vers une API externe lente : utilisez ctx.waitUntil() pour ne pas bloquer la réponse au client.
  • KV considéré comme une base de données : KV est éventuellement consistant (jusqu’à 60 s pour propager une écriture mondialement). Pour des transactions ACID, utilisez D1.
  • Code Node.js incompatible : Workers utilise les Web APIs (fetch, crypto, Request, Response). Activez nodejs_compat uniquement pour les modules essentiels.
  • Cold start sur D1 : la première requête après inactivité prend 50-100 ms. Maintenez un trafic minimum ou utilisez KV pour les hot paths.
  • CORS manquant : ajoutez Access-Control-Allow-Origin dans toutes les réponses si appelé depuis un navigateur.
  • Secrets commités : wrangler secret uniquement, jamais en variables wrangler.toml ni en .env commité.

Checklist de mise en production

  • [ ] Compte Cloudflare créé et domaine .sn ou .com géré dans leur DNS
  • [ ] Wrangler CLI installé et authentifié
  • [ ] Projet TypeScript initialisé avec wrangler.toml
  • [ ] Compatibility date récente (moins de 6 mois)
  • [ ] Worker testé localement avec wrangler dev
  • [ ] KV / D1 / R2 configurés selon les besoins
  • [ ] Schéma D1 versionné dans Git avec migrations
  • [ ] Secrets stockés via wrangler secret put (jamais en clair)
  • [ ] Domaine personnalisé api.monentreprise.sn mappé
  • [ ] Certificat SSL Universal actif (vérification HTTPS)
  • [ ] Logs surveillés via wrangler tail ou Logpush
  • [ ] Plan Workers Paid activé si trafic > 100 000 req/jour
  • [ ] CI/CD GitHub Actions avec wrangler deploy sur push main
  • [ ] Documentation API partagée (Postman, OpenAPI ou markdown)
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité