Para ver el código completo de una implementación real, puedes revisar el directorio clients/react-server en el repositorio open-source de Patron en GitHub. En este artículo adaptamos y explicamos el enfoque en español y lo reorientamos con recomendaciones prácticas para equipos que crean aplicaciones a medida y software a medida con Vite y React.
Cuando migras desde Next.js a un setup personalizado con Vite, uno de los mayores retos es sustituir getStaticProps y getServerSideProps. Next.js hace muy elegante la obtención de datos en el servidor, pero con Vite SSR debes construir ese flujo por tu cuenta. Aquí verás cómo diseñar un sistema flexible y de alto rendimiento que reemplace esas funciones con un patrón propio llamado loadDataForUrl.
Por qué construir SSR personalizado con Vite. Beneficios principales: control total sobre la lógica de servidor y los patrones de carga de datos, gran velocidad de desarrollo y build, arquitectura flexible sin las restricciones de un framework, soporte nativo de streaming SSR en React 18 y una capa de complejidad más simple y cercana a las APIs de React.
Arquitectura general. El sistema se compone de cuatro piezas básicas. Un servidor Express que gestiona peticiones y orquesta el SSR. Un entry point de servidor que renderiza React a streams. Un entry point de cliente que hidrata la app en el navegador. Y una función de carga de datos del lado servidor que actúa como reemplazo de getStaticProps o getServerSideProps con control de rutas y acceso al request.
Servidor Express. La clave es diferenciar comportamiento en desarrollo y producción. En desarrollo usas el dev server de Vite con middleware y HMR. En producción sirves los assets precompilados con compresión. Este servidor se encargará de inyectar los datos iniciales serializados en la plantilla HTML y de iniciar el streaming SSR para entregar el shell rápidamente y finalizar cuando todo esté listo.
Integración con Vite. En modo desarrollo se levanta el dev server de Vite en modo middleware y se transforma la plantilla index, cargando en caliente el módulo de entry-server. En producción se leen los artefactos compilados del cliente y del servidor y se sirven de forma eficiente con compresión y estáticos.
Reemplazo de getStaticProps. En lugar de las funciones de Next.js, definimos loadDataForUrl. Esta función se ejecuta en cada petición del servidor y permite cargar datos según la ruta, llamar a bases de datos, consumir APIs internas, acceder a cabeceras o sesión y devolver objetos con la forma que necesites para cada página. Si una ruta no requiere datos previos, puede devolver null para ahorrar trabajo.
Canal de renderizado SSR. El manejador principal de peticiones realiza tres pasos críticos. Primero llama a loadDataForUrl para obtener initialData. Después serializa de forma segura ese objeto e inyecta el script con la variable global en la plantilla, evitando problemas de inyección al escapar correctamente caracteres sensibles. Por último inicia el streaming con React 18, escribe el comienzo del HTML en cuanto el shell está listo y cierra cuando todo ha terminado, logrando un excelente TTFB.
Entry point del servidor. El módulo entry-server recibe la URL y el initialData, y devuelve un stream generado con renderToPipeableStream. Allí montas tu App envolviendo con StrictMode e inyectando initialData como prop o a través de un contexto. Es el punto único para configurar Suspense en el servidor y los límites de streaming.
Hidratación en el cliente. En entry-client el navegador toma la marca HTML ya renderizada y, mediante hydrateRoot, hidrata la App usando el mismo objeto initialData que el servidor serializó en la plantilla. Esto evita flashes y discrepancias entre servidor y cliente.
Uso de los datos del servidor en la App. En tu App recibes initialData y lo utilizas para renderizar inmediatamente el contenido. Puedes combinarlo con estados de carga y errores, y complementar con fetch del lado cliente tras navegar a otras rutas. Este patrón unifica SSR y navegación cliente con una API simple.
Configuración de Vite y build. A nivel de configuración se requieren dos builds diferenciadas. Un build de cliente para producir los assets del navegador y un build SSR para generar el bundle de servidor que exporta la función de render. Los scripts de package orquestan ambos pasos y permiten un modo preview que arranca en producción con NODE_ENV apropiado.
Patrones avanzados de carga por ruta. loadDataForUrl puede mapear patrones de URL a funciones de carga especializadas, incluida coincidencia con expresiones regulares simples. Así cada sección del sitio obtiene únicamente los datos necesarios, con posibilidad de reutilizar autenticación, memoización, paginación y control de errores específico por página.
Manejo de errores y estados de carga. Combina Error Boundaries y componentes de loading con Suspense para mostrar feedback progresivo en cliente y servidor. En cliente puedes exponer un endpoint de datos interno que delegue en loadDataForUrl, manteniendo una única fuente de verdad para la lógica de datos.
Estrategia de caché. Implementa caching inteligente en loadDataForUrl con keys por ruta y usuario cuando aplique. Usa tiempos de vida adecuados, invalidación selectiva tras actualizaciones y, si tu infraestructura lo permite, almacena en Redis o en servicios cloud para compartir caché entre instancias.
Beneficios del streaming. Con React 18 consigues tiempos de primera respuesta más rápidos, carga progresiva gracias a Suspense, HTML completo que beneficia al SEO y una mejor experiencia sin parpadeos. Este enfoque es ideal para aplicaciones a medida y software a medida con alto tráfico o múltiples integraciones.
Despliegue y variables de entorno. Centraliza la configuración por entorno en el servidor y pásala de forma controlada a la App. Define flags para activar caché, endpoints internos y credenciales seguras. En contenedores, tu imagen debe compilar cliente y servidor y exponer el puerto del servidor Node, listo para producción.
Comparativa con Next.js. Next.js ofrece baja complejidad inicial y un gran ecosistema. Un SSR personalizado con Vite ofrece mayor control, velocidad de desarrollo y build excelentes y una arquitectura más abierta. A cambio, asumes una complejidad media al construir tu pipeline y tu patrón de datos.
Conclusión. Con Vite puedes crear un SSR moderno y eficiente manteniendo control total sobre tus patrones de datos. El patrón loadDataForUrl es una alternativa flexible a getStaticProps y getServerSideProps, compatible con streaming SSR y con un gran desempeño en producción. Este enfoque escala desde blogs simples hasta plataformas complejas con autenticación, bases de datos, APIs internas y tiempos de respuesta por debajo de 100 ms.
Acerca de Q2BSTUDIO. Somos una empresa de desarrollo de software y aplicaciones a medida, especialistas en inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio y power bi, automatización de procesos, agentes IA e ia para empresas. Si buscas un socio tecnológico para diseñar una plataforma con SSR y arquitectura moderna, descubre cómo abordamos proyectos de principio a fin en desarrollo de aplicaciones y software multiplataforma. Para impulsar casos de uso con modelos y automatizaciones, visita también nuestra oferta de inteligencia artificial para empresas.
Palabras clave recomendadas para posicionamiento relacionadas con este contenido. Aplicaciones a medida, software a medida, inteligencia artificial, ciberseguridad, servicios cloud aws y azure, servicios inteligencia de negocio, ia para empresas, agentes IA, power bi.
Si necesitas una guía personalizada para adaptar este patrón a tu stack o consolidar un pipeline de CI CD con pruebas, métricas y observabilidad, contáctanos y te ayudamos a llevar tu SSR con Vite a producción con seguridad, rendimiento y escalabilidad.