Back

Renderizado del lado del servidor con Preact

Renderizado del lado del servidor con Preact

Si has creado aplicaciones con React y Vite, ya entiendes el renderizado del lado del cliente. El navegador descarga un bundle de JavaScript, lo ejecuta y construye el DOM. Funciona, pero los usuarios con conexiones lentas se quedan mirando una pantalla en blanco mientras se carga ese bundle. El renderizado del lado del servidor con Preact resuelve esto enviando HTML listo para mostrar desde el servidor. El reducido tamaño del runtime de Preact hace que esa compensación resulte especialmente atractiva para aplicaciones enfocadas en el rendimiento.

Este artículo explica cómo funciona el SSR con Preact, qué herramientas intervienen y cómo la hidratación conecta el HTML renderizado en el servidor con una aplicación interactiva en vivo.

Puntos clave

  • El SSR de Preact renderiza tu árbol de componentes a una cadena HTML en el servidor, ofreciendo a los usuarios contenido visible antes de que se ejecute cualquier JavaScript.
  • El paquete preact-render-to-string proporciona APIs de renderizado síncronas, asíncronas y de streaming para adaptarse a distintas necesidades de aplicación.
  • La hidratación añade interactividad al HTML renderizado en el servidor usando hydrate en lugar de render, preservando el DOM existente.
  • Un flujo de trabajo basado en Vite con @preact/preset-vite es el estándar moderno para nuevos proyectos Preact con soporte SSR.
  • Evita los desajustes de hidratación manteniendo coherente la salida entre servidor y cliente — sin timestamps, IDs aleatorios ni acceso a window durante la pasada del servidor.

¿Qué es el SSR de Preact y por qué importa?

Con SSR, tu árbol de componentes se renderiza a una cadena HTML en el servidor antes de que el navegador reciba nada. El usuario ve el contenido inmediatamente. JavaScript se carga en segundo plano y añade la interactividad después.

Los beneficios prácticos son reales:

  • Tiempos de carga percibidos más rápidos — el contenido visible llega con la respuesta HTTP inicial.
  • Mejor SEO — los crawlers leen HTML completamente formado sin ejecutar JavaScript.
  • Resiliencia — las páginas siguen siendo legibles incluso si el JS del lado del cliente falla o es lento.

Preact es particularmente adecuado para SSR porque su pequeño runtime añade una sobrecarga mínima.

La herramienta principal: preact-render-to-string

El SSR de Preact depende de preact-render-to-string, un paquete separado que se encarga del renderizado en el servidor.

npm install preact-render-to-string

Renderizado síncrono

Para componentes sin dependencias asíncronas, renderToString convierte tu árbol de componentes a HTML en una sola pasada:

import { renderToString } from 'preact-render-to-string';

const App = () => <h1>Hello from the server</h1>;
const html = renderToString(<App />);
// → <h1>Hello from the server</h1>

Renderizado asíncrono

Cuando los componentes obtienen datos o utilizan Suspense con fragmentos cargados de forma diferida, usa renderToStringAsync en su lugar. Espera a que las promesas y el trabajo de renderizado asíncrono se completen antes de devolver la cadena HTML final.

import { renderToStringAsync } from 'preact-render-to-string';

const html = await renderToStringAsync(<App />);

Streaming

Para páginas más grandes, las APIs de streaming te permiten enviar HTML al navegador por fragmentos a medida que cada sección se renderiza. renderToPipeableStream está orientado a los streams de Node.js, mientras que renderToReadableStream se dirige a entornos que usan la Web Streams API, incluyendo plataformas como Cloudflare Workers, Deno y Bun. El streaming mejora el Time to First Byte (TTFB) sin esperar a que se complete el renderizado completo.

Hidratación en Preact: conectando el HTML con la interactividad

Enviar HTML estático es solo la mitad del trabajo. Para hacer la página interactiva, Preact necesita hidratar el DOM existente — adjuntando event listeners y estado sin volver a renderizar desde cero.

import { hydrate } from 'preact';
import { App } from './app.js';

hydrate(<App />, document.getElementById('root'));

Usa hydrate en lugar de render cuando el DOM ya haya sido producido por el servidor. Usar render descartaría el HTML del servidor y lo reconstruiría, frustrando el propósito.

Los desajustes de hidratación ocurren cuando el HTML renderizado en el servidor no coincide con lo que el cliente renderizaría. Las causas comunes incluyen renderizar timestamps, IDs aleatorios o leer window durante la pasada del servidor. Mantén coherente la lógica de los componentes entre servidor y cliente para evitarlos.

SSR con Preact y Vite: la configuración moderna

Para nuevos proyectos, un flujo de trabajo basado en Vite es la opción práctica por defecto. La guía de SSR de Vite documenta el patrón de doble build: una compilación apuntando al entry del servidor y otra para el bundle del cliente. Preact se integra limpiamente con @preact/preset-vite, que maneja JSX, aliases y la configuración específica de Preact.

Para equipos que prefieren un punto de partida más estructurado, preact-iso proporciona utilidades ligeras de enrutamiento y prerenderizado diseñadas específicamente para proyectos Preact con Vite.

Aspectos a tener en cuenta

El SSR de Preact comparte fundamentos conceptuales con el SSR de React, pero no es idéntico en todos los detalles de implementación. Algunas APIs de SSR específicas de React no tienen equivalentes directos, y el ecosistema en torno a Preact es más pequeño — una compensación razonable a cambio de las ganancias en tamaño y rendimiento.

El patrón que funciona de forma fiable: obtén tus datos antes de renderizar, pásalos como props, renderiza a string en el servidor e hidrata en el cliente. Empieza ahí, y luego añade streaming o patrones de renderizado más avanzados cuando tengas una razón para hacerlo.

Conclusión

El SSR de Preact ofrece una vía ligera y enfocada en el rendimiento para crear aplicaciones renderizadas en el servidor sin la sobrecarga de un framework más grande. Combinando preact-render-to-string para la pasada del servidor, hydrate para la activación del lado del cliente y Vite para el pipeline de build, obtienes una configuración rápida de desplegar y fácil de razonar. Comienza con el flujo básico de render e hidratación, mantén alineadas las salidas de servidor y cliente, y recurre al streaming solo cuando la escala de tu aplicación lo justifique.

Preguntas frecuentes

Elige el SSR de Preact cuando el tamaño del bundle, el rendimiento de arranque en frío o el despliegue en edge importen más que el acceso al ecosistema más amplio de React. El pequeño runtime de Preact es ideal para sitios con mucho contenido, páginas de marketing y despliegues basados en workers. Quédate con el SSR de React si dependes de bibliotecas específicas de React o necesitas APIs como React Server Components que Preact no replica.

Asegúrate de que el servidor y el cliente rendericen la misma salida para los mismos props. Evita valores no deterministas durante el renderizado inicial, como Date.now, Math.random o globales propios del navegador como window y localStorage. Si necesitas contenido exclusivo del cliente, renderiza un placeholder estable en el servidor y actualízalo dentro de un effect después de que se complete la hidratación.

Muchas bibliotecas de React funcionan a través del alias preact/compat, que mapea las importaciones de React a equivalentes de Preact. Sin embargo, las bibliotecas que dependen de funcionalidades de SSR específicas de React, como React Server Components o internals de renderizado, pueden no comportarse correctamente. Prueba cada dependencia en tu pipeline de SSR antes de comprometerte.

Probablemente no. El streaming compensa cuando las páginas son grandes, con muchos datos o tienen secciones que se resuelven a distintas velocidades. Para un sitio pequeño típico, renderToString o renderToStringAsync producen resultados con la suficiente rapidez como para que el streaming añada complejidad sin un beneficio medible. Empieza con las APIs más simples, síncronas o asíncronas, y adopta el streaming solo cuando el TTFB se convierta en un cuello de botella real.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay