Retour au blog

Serverless et Edge Computing : L'Avenir du Développement Web en 2025

Salut HaWkers, imaginez une architecture où vous n'avez pas besoin de gérer de serveurs, votre application scale automatiquement de 0 à des millions d'utilisateurs, et la latence est toujours inférieure à 50ms, peu importe où se trouve votre utilisateur dans le monde.

Bienvenue dans l'avenir qui est déjà présent : Serverless + Edge Computing.

Comprendre le Paradigme

Serverless : Qu'est-ce qui a Changé ?

// Modèle traditionnel
const traditionalArchitecture = {
  infrastructure: {
    servers: 'Vous gérez EC2, containers, etc',
    scaling: 'Manuel ou auto-scaling groups',
    cost: 'Payé 24/7, même sans usage',
    maintenance: 'Patches, updates, monitoring'
  },

  challenges: [
    'Sur-provisionnement (gaspillage)',
    'Sous-provisionnement (crashes)',
    'Complexité opérationnelle',
    'Cold starts lors du scaling'
  ]
};

// Modèle serverless
const serverlessArchitecture = {
  infrastructure: {
    servers: 'Zéro gestion',
    scaling: 'Automatique et instantané',
    cost: 'Payé uniquement à l\'exécution',
    maintenance: 'Zéro (le provider s\'en occupe)'
  },

  benefits: [
    'Scale de 0 à l\'infini automatiquement',
    'Coût proportionnel à l\'usage',
    'Déploiement en secondes',
    'Focus 100% sur le code'
  ]
};

Edge Computing : Plus Près de l'Utilisateur

// Traditionnel : Serveur centralisé
const traditional = {
  user_location: 'Paris, France',
  server_location: 'us-east-1 (Virginia, USA)',
  latency: '~200ms', // 😔
  cold_start: '~1000ms'
};

// Edge : Serveur distribué globalement
const edge = {
  user_location: 'Paris, France',
  server_location: 'Nœud Edge à Paris',
  latency: '~15ms', // 🚀
  cold_start: '~0ms (always warm)'
};

Principales Plateformes en 2025

1. Cloudflare Workers

// Cloudflare Worker - S'exécute dans 300+ villes globalement
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // Edge KV Storage - Latence <50ms globalement
    const value = await env.MY_KV.get(url.pathname);

    if (value) {
      return new Response(value, {
        headers: { 'Content-Type': 'application/json' }
      });
    }

    // Récupérer depuis l'origine si pas en cache
    const response = await fetch(`https://api.example.com${url.pathname}`);
    const data = await response.text();

    // Cache sur l'edge pour les prochaines requêtes
    ctx.waitUntil(env.MY_KV.put(url.pathname, data, {
      expirationTtl: 3600
    }));

    return new Response(data);
  }
};

// Déploiement
// wrangler publish
// ✅ Déploiement global en < 10 secondes

Cas d'utilisation :

  • Proxys API
  • Edges d'authentification
  • Tests A/B
  • Protection contre les bots
  • Routage basé sur la géolocalisation

2. Vercel Edge Functions

// Vercel Edge Function - Powered by V8 isolates
import { NextRequest, NextResponse } from 'next/server';

export const config = {
  runtime: 'edge',
};

export default async function middleware(req: NextRequest) {
  const country = req.geo?.country || 'US';
  const city = req.geo?.city || 'Unknown';

  // Personnaliser la réponse par localisation
  if (country === 'FR') {
    return NextResponse.rewrite(new URL('/fr', req.url));
  }

  // Tests A/B sur l'edge
  const bucket = Math.random() > 0.5 ? 'A' : 'B';
  const response = NextResponse.next();
  response.cookies.set('bucket', bucket);

  return response;
}

// Route API Edge
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const userId = searchParams.get('userId');

  // Fetch de données avec très faible latence
  const response = await fetch(`https://api.example.com/users/${userId}`, {
    // Edge caching
    next: { revalidate: 60 }
  });

  const data = await response.json();

  return Response.json(data);
}

3. AWS Lambda@Edge

// Lambda@Edge - Emplacements edge CloudFront
exports.handler = async (event) => {
  const request = event.Records[0].cf.request;
  const headers = request.headers;

  // Détecter l'appareil
  const userAgent = headers['user-agent'][0].value;
  const isMobile = /Mobile/i.test(userAgent);

  // Rediriger vers la version optimisée
  if (isMobile && !request.uri.includes('/mobile')) {
    return {
      status: '302',
      headers: {
        location: [{
          key: 'Location',
          value: `/mobile${request.uri}`
        }]
      }
    };
  }

  return request;
};

4. Deno Deploy

// Deno Deploy - TypeScript natif sur l'edge
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";

const kv = await Deno.openKv();

serve(async (req) => {
  const url = new URL(req.url);

  if (url.pathname === "/api/counter") {
    // Store KV sur l'edge
    const count = await kv.get(["counter"]);
    const newCount = (count.value as number || 0) + 1;

    await kv.set(["counter"], newCount);

    return new Response(JSON.stringify({ count: newCount }), {
      headers: { "Content-Type": "application/json" }
    });
  }

  return new Response("Bonjour depuis l'edge ! 🦕");
});

// Déploiement : deno deploy --project=myapp main.ts

Architecture Serverless Complète

Exemple d'application full-stack serverless :

// 1. Frontend : Next.js sur Vercel
// app/page.tsx
export default async function HomePage() {
  const data = await fetch('https://api.myapp.com/posts', {
    next: { revalidate: 60 } // ISR
  });

  const posts = await data.json();

  return (
    <div>
      {posts.map(post => (
        <PostCard key={post.id} {...post} />
      ))}
    </div>
  );
}

// 2. API : Edge Functions
// app/api/posts/route.ts
export const runtime = 'edge';

export async function GET() {
  // Connecter à la database (Planetscale, Neon, etc)
  const posts = await db.query('SELECT * FROM posts ORDER BY created_at DESC LIMIT 10');

  return Response.json(posts);
}

// 3. Background Jobs : AWS Lambda
// lambda/process-image.ts
import { S3Event } from 'aws-lambda';
import sharp from 'sharp';

export async function handler(event: S3Event) {
  for (const record of event.Records) {
    const bucket = record.s3.bucket.name;
    const key = decodeURIComponent(record.s3.object.key);

    // Télécharger l'image
    const image = await s3.getObject({ Bucket: bucket, Key: key });

    // Traiter avec sharp
    const resized = await sharp(image.Body)
      .resize(800, 600, { fit: 'cover' })
      .webp({ quality: 80 })
      .toBuffer();

    // Upload de la version traitée
    await s3.putObject({
      Bucket: bucket,
      Key: `processed/${key}`,
      Body: resized
    });
  }
}

// 4. Real-time : WebSockets serverless (Cloudflare Durable Objects)
export class ChatRoom {
  constructor(private state: DurableObjectState) {}

  async fetch(request: Request) {
    if (request.headers.get('Upgrade') === 'websocket') {
      const pair = new WebSocketPair();
      const [client, server] = Object.values(pair);

      this.handleSession(server);

      return new Response(null, {
        status: 101,
        webSocket: client
      });
    }

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

  async handleSession(websocket: WebSocket) {
    websocket.accept();

    websocket.addEventListener('message', async (event) => {
      // Broadcast à tous les connectés
      this.state.getWebSockets().forEach(ws => {
        ws.send(event.data);
      });
    });
  }
}

Patterns et Bonnes Pratiques

1. Optimisation du Cold Start

// ❌ Éviter : Imports lourds
import * as AWS from 'aws-sdk'; // 30MB+
import * as lodash from 'lodash'; // Toute la bibliothèque

export async function handler() {
  // Cold start : ~3000ms
}

// ✅ Mieux : Imports spécifiques
import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3';
import debounce from 'lodash/debounce';

export async function handler() {
  // Cold start : ~500ms
}

// ✅ Idéal : Lazy loading
export async function handler(event) {
  if (event.action === 'process-image') {
    // Importer uniquement quand nécessaire
    const sharp = await import('sharp');
    // ...
  }
}

2. Stratégie de Cache Edge

// Stratégie de cache en plusieurs couches
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const id = searchParams.get('id');

  // Couche 1 : Edge KV (< 10ms)
  const cached = await env.KV.get(`post:${id}`);
  if (cached) {
    return new Response(cached, {
      headers: {
        'Content-Type': 'application/json',
        'X-Cache': 'HIT-EDGE'
      }
    });
  }

  // Couche 2 : Database (< 50ms avec Planetscale/Neon)
  const post = await db.query('SELECT * FROM posts WHERE id = ?', [id]);

  if (post) {
    // Cache sur l'edge pour les prochaines requêtes
    await env.KV.put(`post:${id}`, JSON.stringify(post), {
      expirationTtl: 3600
    });

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

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

3. Transactions Distribuées

// Utiliser une architecture event-driven
// Pub/Sub avec Cloudflare Queues ou AWS EventBridge

// Producer (Edge Function)
export async function POST(request: Request) {
  const order = await request.json();

  // Publier un événement au lieu de traiter de manière synchrone
  await env.QUEUE.send({
    type: 'ORDER_CREATED',
    data: order
  });

  return Response.json({
    status: 'processing',
    orderId: order.id
  });
}

// Consumer (Lambda/Worker)
export async function processOrder(event) {
  const { data: order } = event;

  // Traiter de manière asynchrone
  await Promise.all([
    chargePayment(order),
    updateInventory(order),
    sendConfirmationEmail(order)
  ]);

  // Publier un événement de completion
  await publishEvent({
    type: 'ORDER_COMPLETED',
    orderId: order.id
  });
}

Coûts : Serverless vs Traditionnel

// Comparaison de coût mensuel
const costComparison = {
  traditional_ec2: {
    instance: 't3.medium 24/7',
    monthly_cost: '30,40€',
    load_balancer: '16,20€',
    total: '46,60€',

    traffic: '1M requêtes/mois',
    notes: 'Payé même sans utilisation, nécessite un scaling manuel'
  },

  serverless_lambda: {
    requests: '1M requêtes @ 0,20€/million',
    compute: '100ms avg @ 0,0000166667€/GB-sec',
    monthly_cost: '5,00€',
    total: '5,00€',

    notes: 'Payé uniquement à l\'usage, scale automatiquement'
  },

  serverless_edge: {
    cloudflare_workers: {
      requests: '10M requêtes/mois',
      bundled_plan: '5€/mois',
      overage: '0,50€/million',
      total: '5,00€'
    },

    vercel_edge: {
      requests: '100k edge/mois (gratuit)',
      overage: '20€/million',
      typical_cost: '0€ - 10€'
    }
  },

  savings: '~90% vs traditionnel'
};

Limitations et Compromis

Limitations Actuelles

const edgeLimitations = {
  cloudflare_workers: {
    cpu_time: '50ms gratuit, 30s payant',
    memory: '128MB',
    bundle_size: '1MB compressé',
    no_file_system: true,
    no_native_binaries: true
  },

  vercel_edge: {
    cpu_time: '30s max',
    memory: '128MB',
    bundle_size: '1MB - 4MB',
    no_node_api: 'APIs Node.js limitées'
  },

  aws_lambda: {
    timeout: '15 minutes max',
    memory: '128MB - 10GB',
    cold_start: '~500ms - 3s',
    package_size: '250MB'
  }
};

// Quand NE PAS utiliser edge/serverless
const notSuitableFor = [
  'Connexions WebSocket de longue durée',
  'Traitement vidéo lourd (> 30s)',
  'Entraînement Machine Learning',
  'Opérations de système de fichiers complexes',
  'Connexions database persistantes traditionnelles'
];

L'Avenir : 2026 et Au-delà

const futureOfServerless = {
  trends: {
    wasm_on_edge: {
      description: 'WASM s\'exécutant sur l\'edge pour performance maximale',
      players: ['Cloudflare', 'Fastly Compute@Edge', 'Vercel'],
      benefit: 'Cold start ~0ms, n\'importe quel langage'
    },

    ai_on_edge: {
      description: 'Modèles d\'IA s\'exécutant sur l\'edge',
      use_cases: [
        'Reconnaissance d\'images',
        'Modération de contenu',
        'Personnalisation',
        'Chatbots'
      ]
    },

    edge_databases: {
      description: 'Databases distribuées globalement',
      examples: ['Planetscale', 'Neon', 'Turso', 'Cloudflare D1'],
      latency: '< 10ms partout'
    },

    serverless_gpu: {
      description: 'Accès GPU en fonctions serverless',
      use_cases: [
        'Inférence IA',
        'Traitement vidéo',
        'Calcul scientifique'
      ]
    }
  },

  predictions: {
    '2026': 'Edge computing dans 60% des apps web',
    '2027': 'Serverless standard pour les nouveaux projets',
    '2028': 'Edge AI mainstream'
  }
};

Checklist de Migration

## Migrer vers Serverless/Edge

### Analyse
- [ ] Identifier les parties stateless de l'application
- [ ] Mapper les dépendances externes
- [ ] Évaluer les requirements de latence
- [ ] Estimer les coûts (utiliser les calculatrices des providers)

### Préparation
- [ ] Refactorer en fonctions petites et focalisées
- [ ] Implémenter la logique de retry
- [ ] Configurer le monitoring (Datadog, New Relic, Sentry)
- [ ] Préparer un plan de rollback

### Migration Graduelle
- [ ] Commencer avec les endpoints de lecture (GET)
- [ ] Ajouter les opérations d'écriture (POST/PUT)
- [ ] Migrer les background jobs
- [ ] Migrer les fonctionnalités critiques en dernier

### Post-Migration
- [ ] Monitorer les coûts quotidiennement
- [ ] Optimiser les cold starts
- [ ] Ajuster les timeouts et la mémoire
- [ ] Documenter l'architecture

Si vous êtes passionné par les architectures modernes, je vous recommande de jeter un œil à un autre article : React Foundation : La Nouvelle Ère de l'Écosystème React Sous la Linux Foundation où vous découvrirez comment l'écosystème React évolue pour supporter ces nouvelles architectures.

C'est parti ! 🦅

📚 Vous Voulez Approfondir Vos Connaissances en JavaScript ?

Cet article a couvert Serverless et Edge Computing, mais il y a beaucoup plus à explorer dans le monde du développement moderne.

Les développeurs qui investissent dans des connaissances solides et structurées tendent à avoir plus d'opportunités sur le marché.

Matériel d'Étude Complet

Si vous voulez maîtriser JavaScript du basique à l'avancé, j'ai préparé un guide complet :

Options d'investissement :

  • €9,90 (paiement unique)

👉 Découvrir le Guide JavaScript

💡 Matériel mis à jour avec les meilleures pratiques du marché

Commentaires (0)

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

Ajouter des commentaires