Retour au blog

Edge Computing avec JavaScript : Cloudflare Workers, Vercel Edge et Deno Deploy

Salut HaWkers, l'edge computing transforme la façon dont nous développons des applications web. Au lieu de traiter les requêtes sur un serveur central distant, le code s'exécute sur des points de présence distribués mondialement, réduisant drastiquement la latence.

Et le meilleur : vous pouvez utiliser JavaScript pour cela. Explorons les principales plateformes et comprenons quand utiliser chacune.

Qu'est-ce que l'Edge Computing

L'edge computing déplace le calcul plus près de l'utilisateur final. Au lieu qu'une requête voyage des milliers de kilomètres jusqu'à un data center central, elle est traitée au point de présence le plus proche.

Avantages pratiques :

  • Latence réduite (< 50ms mondialement)
  • Meilleure expérience utilisateur
  • Charge réduite sur le serveur d'origine
  • Possibilité de personnalisation par région
  • Cold starts pratiquement inexistants

Cas d'usage idéaux :

  • APIs à faible latence
  • Authentification et autorisation
  • Redirections intelligentes
  • A/B testing
  • Personnalisation de contenu
  • Rate limiting
  • Transformation de réponses

Cloudflare Workers

Cloudflare Workers a été pionnier dans l'edge computing avec JavaScript. Utilise le runtime V8 isolates, qui est différent du Node.js traditionnel.

Caractéristiques

Points forts :

  • Plus grand réseau edge (300+ localisations)
  • Cold start pratiquement zéro
  • Prix compétitif
  • Écosystème mature (KV, Durable Objects, R2)
  • Support WebSockets

Limitations :

  • Runtime n'est pas Node.js (certaines APIs différentes)
  • Limite de CPU time par requête
  • Courbe d'apprentissage pour les fonctionnalités avancées

Exemple Pratique

// src/index.js - Cloudflare Worker
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // Routage basique
    if (url.pathname === '/api/hello') {
      return new Response(JSON.stringify({
        message: 'Hello from the edge!',
        location: request.cf?.city || 'unknown',
        country: request.cf?.country || 'unknown',
      }), {
        headers: { 'Content-Type': 'application/json' },
      });
    }

    // Cache avec KV Storage
    if (url.pathname.startsWith('/api/cached/')) {
      const key = url.pathname.replace('/api/cached/', '');
      const cached = await env.MY_KV.get(key);

      if (cached) {
        return new Response(cached, {
          headers: {
            'Content-Type': 'application/json',
            'X-Cache': 'HIT',
          },
        });
      }

      // Récupérer de l'origin et mettre en cache
      const data = await fetchFromOrigin(key);
      await env.MY_KV.put(key, JSON.stringify(data), {
        expirationTtl: 3600, // 1 heure
      });

      return new Response(JSON.stringify(data), {
        headers: {
          'Content-Type': 'application/json',
          'X-Cache': 'MISS',
        },
      });
    }

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

async function fetchFromOrigin(key) {
  const response = await fetch(`https://api.origin.com/data/${key}`);
  return response.json();
}

Configuration

# wrangler.toml
name = "my-edge-api"
main = "src/index.js"
compatibility_date = "2025-11-01"

[[kv_namespaces]]
binding = "MY_KV"
id = "abc123"

[vars]
API_KEY = "your-api-key"

Vercel Edge Functions

Vercel Edge Functions s'intègre parfaitement avec Next.js et d'autres frameworks. Utilise le même runtime V8 isolates.

Caractéristiques

Points forts :

  • Intégration native avec Next.js
  • Deploy automatique via Git
  • UI excellente pour le monitoring
  • Middleware puissant
  • Facile à démarrer

Limitations :

  • Moins de localisations que Cloudflare
  • Le pricing peut escalader vite
  • Moins de ressources de storage natives

Exemple avec Next.js

// middleware.ts - Vercel Edge Middleware
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
  const { pathname, geo } = request.nextUrl;

  // Géolocalisation
  const country = geo?.country || 'US';
  const city = geo?.city || 'Unknown';

  // Redirection par région
  if (pathname === '/' && country === 'FR') {
    return NextResponse.redirect(new URL('/fr', request.url));
  }

  // A/B Testing
  const bucket = request.cookies.get('ab-bucket')?.value;
  if (!bucket && pathname === '/landing') {
    const newBucket = Math.random() < 0.5 ? 'A' : 'B';
    const response = NextResponse.rewrite(
      new URL(`/landing/${newBucket}`, request.url)
    );
    response.cookies.set('ab-bucket', newBucket, {
      maxAge: 60 * 60 * 24 * 30, // 30 jours
    });
    return response;
  }

  // Headers personnalisés
  const response = NextResponse.next();
  response.headers.set('X-Geo-Country', country);
  response.headers.set('X-Geo-City', city);

  return response;
}

export const config = {
  matcher: ['/', '/landing/:path*', '/api/:path*'],
};

Edge API Route

// app/api/edge/route.ts
import { NextRequest } from 'next/server';

export const runtime = 'edge';

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get('q');

  // Traitement léger sur l'edge
  const results = await searchIndex(query);

  return Response.json({
    results,
    processed_at: new Date().toISOString(),
    edge_location: request.geo?.city,
  });
}

async function searchIndex(query: string | null) {
  // Logique de recherche optimisée pour l'edge
  return [];
}

Deno Deploy

Deno Deploy utilise le runtime Deno, offrant TypeScript natif et des APIs modernes.

Caractéristiques

Points forts :

  • TypeScript natif sans build
  • APIs Web standard (fetch, Request, Response)
  • Deno KV intégré
  • Broadcast Channels pour communication
  • Free tier généreux

Limitations :

  • Écosystème plus petit que Node.js
  • Moins d'intégrations entreprise
  • Courbe d'apprentissage si vous venez de Node.js

Exemple Pratique

// main.ts - Deno Deploy
import { serve } from "https://deno.land/std@0.220.0/http/server.ts";

const kv = await Deno.openKv();

async function handler(request: Request): Promise<Response> {
  const url = new URL(request.url);

  // API de Rate Limiting
  if (url.pathname.startsWith('/api/')) {
    const clientIP = request.headers.get('x-forwarded-for') || 'unknown';
    const rateLimit = await checkRateLimit(clientIP);

    if (!rateLimit.allowed) {
      return new Response(JSON.stringify({
        error: 'Rate limit exceeded',
        retry_after: rateLimit.retryAfter,
      }), {
        status: 429,
        headers: {
          'Content-Type': 'application/json',
          'Retry-After': String(rateLimit.retryAfter),
        },
      });
    }
  }

  // Route principale
  if (url.pathname === '/api/data') {
    const data = await fetchData();
    return Response.json(data);
  }

  // Cache avec Deno KV
  if (url.pathname.startsWith('/api/cached/')) {
    const key = url.pathname.replace('/api/cached/', '');
    const cached = await kv.get(['cache', key]);

    if (cached.value) {
      return Response.json(cached.value, {
        headers: { 'X-Cache': 'HIT' },
      });
    }

    const data = await fetchFromOrigin(key);
    await kv.set(['cache', key], data, {
      expireIn: 3600 * 1000, // 1 heure
    });

    return Response.json(data, {
      headers: { 'X-Cache': 'MISS' },
    });
  }

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

async function checkRateLimit(clientIP: string) {
  const key = ['ratelimit', clientIP];
  const now = Date.now();
  const windowMs = 60000; // 1 minute
  const maxRequests = 100;

  const entry = await kv.get<{ count: number; resetAt: number }>(key);

  if (!entry.value || now > entry.value.resetAt) {
    await kv.set(key, { count: 1, resetAt: now + windowMs });
    return { allowed: true };
  }

  if (entry.value.count >= maxRequests) {
    return {
      allowed: false,
      retryAfter: Math.ceil((entry.value.resetAt - now) / 1000),
    };
  }

  await kv.set(key, {
    count: entry.value.count + 1,
    resetAt: entry.value.resetAt,
  });

  return { allowed: true };
}

async function fetchData() {
  return { message: 'Hello from Deno Deploy!' };
}

async function fetchFromOrigin(key: string) {
  return { key, data: 'origin data' };
}

serve(handler);

Comparatif des Plateformes

Performance et Réseau

Plateforme Localisations Cold Start CPU Limit
Cloudflare 300+ ~0ms 50ms
Vercel Edge 100+ ~25ms 25ms
Deno Deploy 35+ ~10ms 50ms

Storage et Ressources

Plateforme KV Storage Durable Objects Database
Cloudflare ✅ KV D1 (SQLite)
Vercel Via Upstash Via intégration
Deno ✅ Deno KV Deno KV

Pricing (Tier Gratuit)

Plateforme Requests/jour CPU Time Bandwidth
Cloudflare 100k 10ms/req Illimité
Vercel 100k - 100GB
Deno 1M/mois - 100GB

Quand Utiliser l'Edge Computing

Utilisez l'Edge Quand :

  • Vous avez besoin d'une faible latence globale
  • Vous faites de la transformation légère de requêtes
  • Vous implémentez l'authentification/autorisation
  • Vous servez du contenu personnalisé par région
  • Vous avez besoin de rate limiting distribué
  • Vous faites des redirections intelligentes

Évitez l'Edge Quand :

  • Vous avez besoin de traitement CPU intensif
  • Vous nécessitez une connexion à une base de données traditionnelle
  • Vous avez des dépendances Node.js incompatibles
  • Vous avez besoin de traitement batch
  • Vous avez des exigences de compliance nécessitant une région spécifique

Patterns d'Architecture

Edge + Origin

// Pattern : Edge comme gateway, Origin pour logique lourde
async function handler(request: Request) {
  // Validation rapide sur l'edge
  const authResult = await validateAuth(request);
  if (!authResult.valid) {
    return new Response('Unauthorized', { status: 401 });
  }

  // Cache check sur l'edge
  const cacheKey = getCacheKey(request);
  const cached = await cache.get(cacheKey);
  if (cached) {
    return new Response(cached);
  }

  // Forward vers origin si nécessaire
  const originResponse = await fetch('https://origin.example.com/api', {
    headers: {
      'Authorization': `Bearer ${authResult.token}`,
      'X-User-Id': authResult.userId,
    },
  });

  // Cache response sur l'edge
  const data = await originResponse.text();
  await cache.put(cacheKey, data, { ttl: 300 });

  return new Response(data);
}

Conclusion

L'edge computing avec JavaScript offre une façon puissante d'améliorer la performance des applications web. Le choix de la plateforme dépend de votre contexte :

Cloudflare Workers est idéal pour ceux qui ont besoin du plus grand réseau de distribution et de fonctionnalités avancées comme Durable Objects.

Vercel Edge Functions est parfait pour les projets Next.js qui veulent une intégration seamless et une bonne expérience développeur.

Deno Deploy est excellent pour ceux qui veulent TypeScript natif et sont à l'aise avec l'écosystème Deno.

La bonne nouvelle est que toutes les plateformes utilisent des APIs Web standard, donc beaucoup de code est portable entre elles.

Si vous êtes intéressé à explorer davantage les architectures modernes avec JavaScript, je recommande de consulter l'article Node.js vs Deno vs Bun : Quel Runtime JavaScript Choisir en 2025 pour mieux comprendre les runtimes qui alimentent ces plateformes edge.

C'est parti ! 🦅

Commentaires (0)

Cet article n'a pas encore de commentaires. Soyez le premier!

Ajouter des commentaires