Server-Sent Events

La route API retourne un corps ReadableStream avec content-type: text/event-stream ; la page ouvre un EventSource. bext pilote l'isolat V8 avec un driver progressif — chaque chunk mis en file est transmis au corps HTTP dès que le producteur le vide, de sorte qu'onmessage se déclenche en temps réel au rythme choisi par le handler (un tick toutes les 750 ms ci-dessous).

Attention
Les routes /api/* bufférisent la réponse complète avant de la livrer — EventSource ne reçoit pas les chunks en temps réel depuis une route API PRISM. Utilisez une route dédiée src/app/api/sse/route.ts (pas page.tsx) pour que le driver progressif flush chaque chunk immédiatement.

Flux en direct

src/app/api/sse/route.tsTypeScript
// src/app/api/sse/route.ts — emits text/event-stream
export async function GET(): Promise<Response> {
  const encoder = new TextEncoder();
  const stream = new ReadableStream({
    async start(controller) {
      controller.enqueue(encoder.encode(`data: ${JSON.stringify({tick:0,at:Date.now()})}\n\n`));
      for (let i = 1; i <= 8; i++) {
        await new Promise(r => setTimeout(r, 750));
        controller.enqueue(encoder.encode(`data: ${JSON.stringify({tick:i,at:Date.now()})}\n\n`));
      }
      controller.close();
    },
  });
  return new Response(stream, {
    headers: { "content-type": "text/event-stream" },
  });
}

// page.tsx — client opens an EventSource
const es = new EventSource("/api/sse");
es.onmessage = (e) => render(JSON.parse(e.data));