HTML que llega en pedazos al navegador
Conceptos básicos · agnóstico de stack
Una técnica para enviar HTML al navegador de forma incremental.
El server empieza a responder antes de tener todo el HTML, va emitiendo fragmentos (chunks) y el navegador los va pintando conforme llegan.
No es un estándar nuevo. Es HTTP/1.1 + chunked transfer + HTML.
El navegador espera a tener el documento completo.
Cada fragmento se pinta en cuanto llega.
Clave: no es necesario esperar
al </html> para empezar a mostrar
contenido.
Transfer-Encoding: chunkedHTTP permite al server enviar una respuesta sin conocer el tamaño total por adelantado.
Formato de cada chunk (en bytes crudos):
Cada chunk es tamaño_hex + \n + datos + \n. El
chunk 0 marca el final.
La conexión se mantiene abierta. El server "empuja" HTML al cliente sin que éste tenga que pedirlo.
fetch + ReadableStream: dos APIs
nativas del navegador, ningún framework.
// 1. Abrir el stream
const res = await fetch("/api/messages")
const reader = res.body.getReader()
const decoder = new TextDecoder("utf-8")
let buffer = ""
// 2. Leer hasta que el server cierre
while (true) {
const { value, done } = await reader.read()
if (done) break
buffer += decoder.decode(value, { stream: true })
// 3. Extraer cada <article> completo del buffer
let start = buffer.indexOf("<article")
while (start !== -1) {
const end = buffer.indexOf("</article>", start)
if (end === -1) break
insertHTML(buffer.slice(start, end + 10))
buffer = buffer.slice(end + 10)
start = buffer.indexOf("<article")
}
}
function insertHTML(html) {
const tpl = document.createElement("template")
tpl.innerHTML = html // parsea, no ejecuta
container.appendChild(tpl.content) // se mueve al DOM real
}
¿Por qué es seguro?
<, >,
&, ").
<template> parsea HTML pero
no ejecuta
<script> ni carga
<img>.
DOMPurify ni sanitización
extra en el cliente.
| HTML Streaming | WebSockets | SSE | |
|---|---|---|---|
| Transporte | HTTP/1.1 | Upgrade a WS | HTTP/1.1 |
| Bidireccional | No (server→client) | Sí | No |
| Reconexión | Manual | Manual | Automática |
| Frame | Ninguno (HTML) | Binario/Texto | event:/data: |
| Browser API | fetch + ReadableStream | WebSocket | EventSource |
| Complejidad | Mínima | Media | Baja |
HTML Streaming es el más simple:
sólo HTTP y un loop de flush() en el server.
X-Accel-Buffering: no.
fetch(). SSE lo hace solo.
HTTP chunked + un loop de
flush() en el server
+ fetch con ReadableStream en el
cliente
= HTML Streaming.
Funciona con cualquier stack: no es propio de un framework, es de la web platform.
Listo, no hay más misterio. ✨