Vue Academy · Lección

SSR en streaming con renderToWebStream

renderToWebStream() frente a renderToString(), streaming HTTP, mejora del TTFB y envío de fragmentos

Lección 3 de 413 pasos

SSR en streaming con renderToWebStream es una lección gratuita de Vue Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Vue Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Vue Academy incluye 4 lecciones en total.

De renderToString al streaming

La SSR clásica usa renderToString, que construye todo el HTML en memoria antes de enviar un solo byte. El navegador permanece inactivo hasta que la página completa está lista.

La SSR mediante streaming envía el HTML en chunks a medida que se renderiza la aplicación, por lo que el navegador empieza a analizarlo antes.

Fundamentos de renderToWebStream

El renderizador de servidor de Vue ofrece funciones de streaming. renderToWebStream devuelve un ReadableStream (la API Web Streams), mientras que renderToNodeStream/pipeToNodeWritable se dirigen a la interfaz de streams de Node.

Cada chunk se vacía a medida que se resuelve el árbol de componentes.

import { renderToWebStream } from 'vue/server-renderer'
import { createSSRApp } from 'vue'
import App from './App.vue'

const app = createSSRApp(App)
const stream = renderToWebStream(app)

Enviar el stream a una respuesta HTTP

En un servidor Node, se envía el stream a la respuesta. Con pipeToNodeWritable, se escribe directamente en el writable res y se vacían los chunks a medida que se producen.

import { pipeToNodeWritable } from 'vue/server-renderer'

server.get('*', (req, res) => {
  const app = createSSRApp(App)
  res.write('<!DOCTYPE html><html><body><div id="app">')
  pipeToNodeWritable(app, {}, res)
})

Streaming en un entorno Web/Edge

En entornos edge (Workers, Deno, Bun), se devuelve directamente un Response construido a partir del stream web. No intervienen los streams de Node.

import { renderToWebStream } from 'vue/server-renderer'

export default async function handler(request) {
  const app = createSSRApp(App)
  const stream = renderToWebStream(app)
  return new Response(stream, {
    headers: { 'Content-Type': 'text/html' }
  })
}

Cómo llegan los chunks al navegador

A medida que Vue renderiza los nodos, inserta cadenas HTML serializadas en el stream. La capa HTTP vacía esos bytes inmediatamente. El analizador HTML incremental del navegador renderiza el contenido visible antes de que termine la respuesta.

Por eso el usuario ve el encabezado y el diseño mientras el cuerpo de la página todavía se está transmitiendo.

TTFB: la métrica clave

TTFB (Time To First Byte) mide cuánto se tarda en recibir el primer byte de la respuesta.

Con renderToString, el TTFB incluye todo el tiempo de renderización. Con streaming, el primer chunk sale del servidor casi de inmediato, lo que reduce drásticamente el TTFB y mejora la velocidad percibida.

// renderToString: client waits for full HTML
const html = await renderToString(app) // blocks
res.end(fullPage(html))

// streaming: first bytes flush right away
pipeToNodeWritable(app, {}, res) // non-blocking chunks

Envolver el stream con el HTML del diseño

Normalmente debe enviar la estructura del documento (<head>, las etiquetas de apertura) antes del stream de la aplicación y las etiquetas de cierre después. Escriba el prefijo, envíe la aplicación mediante pipe y escriba el sufijo cuando termine el stream.

res.write('<!DOCTYPE html><head><title>App</title></head>')
res.write('<body><div id="app">')

pipeToNodeWritable(app, ctx, {
  write: (chunk) => res.write(chunk),
  end: () => res.end('</div></body></html>')
})

Gestión de errores durante el streaming

Una vez enviados los bytes, ya no puede cambiar el código de estado HTTP. Gestione los errores de renderización mediante la opción onError (o la ruta de error del writable). Para fallos críticos detectados pronto, prefiera una renderización sin streaming para poder enviar todavía un 500.

pipeToNodeWritable(app, ctx, {
  write: (c) => res.write(c),
  end: () => res.end(suffix),
  destroy: (err) => {
    console.error('Stream failed:', err)
    res.end() // status already sent
  }
})

Hidratación después del streaming

El HTML transmitido mediante streaming sigue hidratándose en el cliente con createSSRApp().mount(). Vue añade los listeners al DOM existente en lugar de recrearlo. El streaming solo afecta a la forma de entregar el marcado, no al funcionamiento de la hidratación.

// client entry
import { createSSRApp } from 'vue'
import App from './App.vue'

createSSRApp(App).mount('#app') // hydrates streamed markup

Streaming y datos asíncronos

En componentes que dependen de datos, resuelva los datos críticos antes o durante el streaming. El streaming resulta especialmente útil cuando partes del árbol son independientes: la estructura se transmite de inmediato mientras las secciones más lentas se renderizan a medida que sus datos están disponibles.

// fetch critical data, then stream the rest
const app = createSSRApp(App, { initialData })
const stream = renderToWebStream(app)
return new Response(stream, {
  headers: { 'Content-Type': 'text/html' }
})

Cuándo elegir streaming

Use streaming para páginas con mucho contenido en las que importen el TTFB y la velocidad percibida, y en las que pueda enviar primero una estructura estable. Use renderToString para páginas pequeñas o cuando necesite controlar por completo el código de estado y las cabeceras finales.

Comprobación rápida

Compruebe su comprensión de la SSR mediante streaming.

Recapitulación

Ha aprendido sobre la SSR mediante streaming:

  • renderToWebStream devuelve un ReadableStream; Node usa pipeToNodeWritable
  • los chunks se vacían a medida que se renderiza el árbol, por lo que el navegador lo analiza de forma incremental
  • esto reduce el TTFB frente al renderToString bloqueante
  • escriba la estructura del documento alrededor del stream; los errores posteriores al primer vaciado no pueden cambiar el estado
  • la hidratación con createSSRApp().mount() no cambia
Gratis para empezar

Aprende HTML con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
42
Lecciones
156

Preguntas frecuentes

¿La lección «SSR en streaming con renderToWebStream» es gratis?

Sí — el texto completo de «SSR en streaming con renderToWebStream» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Vue Academy, actualiza a CoddyKit PRO. El curso de Vue Academy incluye 4 lecciones en total.

¿Qué aprenderé en «SSR en streaming con renderToWebStream»?

renderToWebStream() frente a renderToString(), streaming HTTP, mejora del TTFB y envío de fragmentos Practicas Vue Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Vue Academy?

No se requiere experiencia previa. Vue Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.

¿Cuánto tiempo toma la lección «SSR en streaming con renderToWebStream»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Vue Academy?

Sí. Cada lección de Vue Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Componente Vue Suspense
  2. Componentes asíncronos con defineAsyncComponent
  3. SSR en streaming con renderToWebStream
  4. Estrategias de hidratación diferida
← Volver a Vue Academy