Vue 53: SSR y el Modelo Mental de Nuxt
easy⏱ 5 mincoursevue
Dos renders, una sola app
En SSR, el servidor llama a renderToString(app) y produce un string de HTML que se envía al navegador para lograr un primer pintado rápido; luego el cliente ejecuta ese mismo código de la app y Vue lo 'hidrata': engancha los listeners y los bindings reactivos al DOM que ya existe, en lugar de descartarlo y volver a renderizar desde cero.
// server entry (Node)
import { createSSRApp } from 'vue';
import { renderToString } from 'vue/server-renderer';
const app = createSSRApp(RootComponent);
const html = await renderToString(app);
// respond with an HTML page containing 'html'
// client entry (browser)
import { createSSRApp } from 'vue';
createSSRApp(RootComponent).mount('#app'); // hydrates, doesn't re-render from scratch
Nuxt automatiza todo esto
Nuxt se construye sobre Vue para darte enrutamiento basado en archivos, auto-imports, y un modo de renderizado que eliges por app o por ruta - SSR universal por defecto, generación estática (SSG), o renderizado puramente en el cliente - sin que tengas que escribir a mano la separación entre entrada de servidor y de cliente.
Simulando la brecha en este sandbox
Aquí no hay un servidor real, así que la demo de abajo simula el retraso de red + parseo con un temporizador, pasando de una insignia de 'estático' a 'hidratado' cuando el timer se cumple - esa brecha de tiempo es exactamente lo que percibe un usuario real entre el primer pintado y que la página se vuelva clicable.
Desajustes de hidratación
Si el HTML renderizado en el servidor y el primer render del cliente no coinciden exactamente (por ejemplo, usando Math.random() o Date.now() directamente en una plantilla), Vue registra una advertencia de desajuste de hidratación y puede volver a renderizar - un bug real y muy común en Nuxt.