Modos de Renderizado
Aprende sobre los diferentes modos de renderizado disponibles en Nuxt.
Nuxt soporta diferentes modos de renderizado, renderizado universal, renderizado del lado del cliente pero también ofrece renderizado híbrido y la posibilidad de renderizar tu aplicación en servidores de borde de CDN.
Tanto el navegador como el servidor pueden interpretar el código JavaScript para convertir los componentes de Vue.js en elementos HTML. Este paso se llama renderizado. Nuxt soporta tanto el renderizado universal como el del lado del cliente. Ambos enfoques tienen beneficios y desventajas que cubriremos.
Por defecto, Nuxt utiliza el renderizado universal para proporcionar una mejor experiencia de usuario, rendimiento y optimizar la indexación de motores de búsqueda, pero puedes cambiar los modos de renderizado en una línea de configuración.
Renderizado Universal
Este paso es similar al renderizado del lado del servidor tradicional realizado por aplicaciones PHP o Ruby. Cuando el navegador solicita una URL con el renderizado universal habilitado, Nuxt ejecuta el código JavaScript (Vue.js) en un entorno de servidor y devuelve una página HTML completamente renderizada al navegador. Nuxt también puede devolver una página HTML completamente renderizada desde una caché si la página fue generada de antemano. Los usuarios obtienen inmediatamente la totalidad del contenido inicial de la aplicación, a diferencia del renderizado del lado del cliente.
Una vez que el documento HTML ha sido descargado, el navegador lo interpreta y Vue.js toma el control del documento. El mismo código JavaScript que una vez se ejecutó en el servidor se ejecuta en el cliente (navegador) nuevamente en segundo plano, ahora habilitando la interactividad (de ahí el renderizado universal) al vincular sus oyentes al HTML. Esto se llama Hidratación. Cuando la hidratación está completa, la página puede disfrutar de beneficios como interfaces dinámicas y transiciones de página.
El renderizado universal permite que una aplicación Nuxt proporcione tiempos de carga de página rápidos mientras preserva los beneficios del renderizado del lado del cliente. Además, como el contenido ya está presente en el documento HTML, los rastreadores pueden indexarlo sin sobrecarga.
¿Qué se renderiza en el servidor y qué en el cliente?
Es normal preguntarse qué partes de un archivo Vue se ejecutan en el servidor y/o en el cliente en modo de renderizado universal.
<script setup lang="ts">
const counter = ref(0); // se ejecuta en entornos de servidor y cliente
const handleClick = () => {
counter.value++; // se ejecuta solo en un entorno de cliente
};
</script>
<template>
<div>
<p>Count: {{ counter }}</p>
<button @click="handleClick">Incrementar</button>
</div>
</template>
En la solicitud inicial, la referencia counter
se inicializa en el servidor ya que se renderiza dentro de la etiqueta <p>
. El contenido de handleClick
nunca se ejecuta aquí. Durante la hidratación en el navegador, la referencia counter
se reinicializa. El handleClick
finalmente se vincula al botón; por lo tanto, es razonable deducir que el cuerpo de handleClick
siempre se ejecutará en un entorno de navegador.
Middlewares y páginas se ejecutan en el servidor y en el cliente durante la hidratación. Plugins pueden ser renderizados en el servidor o cliente o ambos. Componentes pueden ser forzados a ejecutarse solo en el cliente también. Composables y utilidades se renderizan según el contexto de su uso.
Beneficios del renderizado del lado del servidor:
- Rendimiento: Los usuarios pueden obtener acceso inmediato al contenido de la página porque los navegadores pueden mostrar contenido estático mucho más rápido que el contenido generado por JavaScript. Al mismo tiempo, Nuxt preserva la interactividad de una aplicación web durante el proceso de hidratación.
- Optimización para Motores de Búsqueda: El renderizado universal entrega todo el contenido HTML de la página al navegador como una aplicación de servidor clásica. Los rastreadores web pueden indexar directamente el contenido de la página, lo que hace que el renderizado universal sea una excelente opción para cualquier contenido que desees indexar rápidamente.
Desventajas del renderizado del lado del servidor:
- Restricciones de desarrollo: Los entornos de servidor y navegador no proporcionan las mismas APIs, y puede ser complicado escribir código que pueda ejecutarse sin problemas en ambos lados. Afortunadamente, Nuxt proporciona pautas y variables específicas para ayudarte a determinar dónde se ejecuta un fragmento de código.
- Costo: Se necesita un servidor en funcionamiento para renderizar páginas sobre la marcha. Esto agrega un costo mensual como cualquier servidor tradicional. Sin embargo, las llamadas al servidor se reducen significativamente gracias al renderizado universal con el navegador tomando el control en la navegación del lado del cliente. Es posible una reducción de costos aprovechando el renderizado del lado del borde.
El renderizado universal es muy versátil y puede adaptarse a casi cualquier caso de uso, y es especialmente apropiado para cualquier sitio web orientado al contenido: blogs, sitios web de marketing, portafolios, sitios de comercio electrónico y mercados.
Para más ejemplos sobre cómo escribir código Vue sin desajustes de hidratación, consulta la documentación de Vue.
Al importar una biblioteca que depende de APIs del navegador y tiene efectos secundarios, asegúrate de que el componente que la importa solo se llame del lado del cliente. Los empaquetadores no eliminan las importaciones de módulos que contienen efectos secundarios.
Renderizado del Lado del Cliente
De fábrica, una aplicación tradicional de Vue.js se renderiza en el navegador (o cliente). Luego, Vue.js genera elementos HTML después de que el navegador descarga y analiza todo el código JavaScript que contiene las instrucciones para crear la interfaz actual.
Beneficios del renderizado del lado del cliente:
- Velocidad de desarrollo: Al trabajar completamente en el lado del cliente, no tenemos que preocuparnos por la compatibilidad del código con el servidor, por ejemplo, al usar APIs solo del navegador como el objeto
window
. - Más económico: Ejecutar un servidor agrega un costo de infraestructura ya que necesitarías ejecutarlo en una plataforma que soporte JavaScript. Podemos alojar aplicaciones solo del cliente en cualquier servidor estático con archivos HTML, CSS y JavaScript.
- Offline: Debido a que el código se ejecuta completamente en el navegador, puede seguir funcionando bien mientras el internet no esté disponible.
Desventajas del renderizado del lado del cliente:
- Rendimiento: El usuario tiene que esperar a que el navegador descargue, analice y ejecute los archivos JavaScript. Dependiendo de la red para la parte de descarga y del dispositivo del usuario para el análisis y ejecución, esto puede tomar tiempo e impactar la experiencia del usuario.
- Optimización para Motores de Búsqueda: La indexación y actualización del contenido entregado a través del renderizado del lado del cliente toma más tiempo que con un documento HTML renderizado en el servidor. Esto está relacionado con la desventaja de rendimiento que discutimos, ya que los rastreadores de motores de búsqueda no esperarán a que la interfaz esté completamente renderizada en su primer intento de indexar la página. Tu contenido tomará más tiempo en mostrarse y actualizarse en las páginas de resultados de búsqueda con un renderizado puramente del lado del cliente.
El renderizado del lado del cliente es una buena opción para aplicaciones web altamente interactivas que no necesitan indexación o cuyos usuarios visitan con frecuencia. Puede aprovechar el almacenamiento en caché del navegador para omitir la fase de descarga en visitas posteriores, como SaaS, aplicaciones de back-office o juegos en línea.
Puedes habilitar el renderizado solo del lado del cliente con Nuxt en tu nuxt.config.ts
:
export default defineNuxtConfig({
ssr: false
})
Si usas ssr: false
, también deberías colocar un archivo HTML en ~/app/spa-loading-template.html
con algún HTML que te gustaría usar para renderizar una pantalla de carga que se renderizará hasta que tu aplicación esté hidratada.
Desplegando una Aplicación Estática Renderizada del Lado del Cliente
Si despliegas tu aplicación en alojamiento estático con los comandos nuxt generate
o nuxt build --prerender
, entonces por defecto, Nuxt renderizará cada página como un archivo HTML estático separado.
Si prerenderizas tu aplicación con los comandos nuxt generate
o nuxt build --prerender
, entonces no podrás usar ningún punto final del servidor ya que no se incluirá ningún servidor en tu carpeta de salida. Si necesitas funcionalidad del servidor, usa nuxt build
en su lugar.
Si estás usando renderizado puramente del lado del cliente, entonces esto podría ser innecesario. Podrías necesitar solo un único archivo index.html
, además de los archivos de respaldo 200.html
y 404.html
, que puedes indicar a tu servidor web estático que sirva para todas las solicitudes.
Para lograr esto, podemos cambiar cómo se prerenderizan las rutas. Solo agrega esto a tus hooks en tu nuxt.config.ts
:
export default defineNuxtConfig({
hooks: {
'prerender:routes' ({ routes }) {
routes.clear() // No generar ninguna ruta (excepto las predeterminadas)
}
},
})
Esto producirá tres archivos:
index.html
200.html
404.html
Los archivos 200.html
y 404.html
podrían ser útiles para el proveedor de alojamiento que estás usando.
Omitiendo la Generación de Respaldo del Cliente
Al prerenderizar una aplicación renderizada del lado del cliente, Nuxt generará por defecto los archivos index.html
, 200.html
y 404.html
. Sin embargo, si necesitas evitar que alguno (o todos) de estos archivos se generen en tu compilación, puedes usar el hook 'prerender:generate'
de Nitro.
export default defineNuxtConfig({
ssr: false,
nitro: {
hooks: {
'prerender:generate'(route) {
const routesToSkip = ['/index.html', '/200.html', '/404.html']
if (routesToSkip.includes(route.route)) {
route.skip = true
}
}
}
}
})
Renderizado Híbrido
El renderizado híbrido permite diferentes reglas de caché por ruta usando Reglas de Ruta y decide cómo el servidor debe responder a una nueva solicitud en una URL dada.
Anteriormente, cada ruta/página de una aplicación Nuxt y servidor debía usar el mismo modo de renderizado, universal o del lado del cliente. En varios casos, algunas páginas podrían generarse en tiempo de compilación, mientras que otras deberían renderizarse del lado del cliente. Por ejemplo, piensa en un sitio web de contenido con una sección de administración. Cada página de contenido debería ser principalmente estática y generada una vez, pero la sección de administración requiere registro y se comporta más como una aplicación dinámica.
Nuxt incluye soporte para reglas de ruta y renderizado híbrido. Usando reglas de ruta puedes definir reglas para un grupo de rutas de nuxt, cambiar el modo de renderizado o asignar una estrategia de caché basada en la ruta.
El servidor de Nuxt registrará automáticamente el middleware correspondiente y envolverá las rutas con manejadores de caché usando la capa de caché de Nitro.
export default defineNuxtConfig({
routeRules: {
// Página de inicio prerenderizada en tiempo de compilación
'/': { prerender: true },
// Página de productos generada bajo demanda, se revalida en segundo plano, almacenada en caché hasta que cambie la respuesta de la API
'/products': { swr: true },
// Páginas de productos generadas bajo demanda, se revalidan en segundo plano, almacenadas en caché por 1 hora (3600 segundos)
'/products/**': { swr: 3600 },
// Página de publicaciones de blog generada bajo demanda, se revalida en segundo plano, almacenada en caché en CDN por 1 hora (3600 segundos)
'/blog': { isr: 3600 },
// Página de publicación de blog generada bajo demanda una vez hasta el próximo despliegue, almacenada en caché en CDN
'/blog/**': { isr: true },
// Panel de administración renderizado solo del lado del cliente
'/admin/**': { ssr: false },
// Agregar encabezados cors en rutas de API
'/api/**': { cors: true },
// Redirigir URLs antiguas
'/old-page': { redirect: '/new-page' }
}
})
Reglas de Ruta
Las diferentes propiedades que puedes usar son las siguientes:
redirect: string
- Define redirecciones del lado del servidor.ssr: boolean
- Desactiva el renderizado del lado del servidor del HTML para secciones de tu aplicación y haz que se rendericen solo en el navegador conssr: false
cors: boolean
- Agrega automáticamente encabezados cors concors: true
- puedes personalizar la salida sobrescribiendo conheaders
headers: object
- Agrega encabezados específicos a secciones de tu sitio - por ejemplo, tus activosswr: number | boolean
- Agrega encabezados de caché a la respuesta del servidor y la almacena en caché en el servidor o proxy inverso por un TTL (tiempo de vida) configurable. La configuraciónnode-server
de Nitro es capaz de almacenar en caché la respuesta completa. Cuando el TTL expira, se enviará la respuesta en caché mientras la página se regenerará en segundo plano. Si se usa true, se agrega un encabezadostale-while-revalidate
sin un MaxAge.isr: number | boolean
- El comportamiento es el mismo queswr
excepto que podemos agregar la respuesta a la caché de CDN en plataformas que lo soportan (actualmente Netlify o Vercel). Si se usatrue
, el contenido persiste hasta el próximo despliegue dentro del CDN.prerender: boolean
- Prerenderiza rutas en tiempo de compilación y las incluye en tu compilación como activos estáticosnoScripts: boolean
- Desactiva la renderización de scripts de Nuxt y sugerencias de recursos JS para secciones de tu sitio.appMiddleware: string | string[] | Record<string, boolean>
- Te permite definir middleware que debería o no ejecutarse para rutas de página dentro de la parte de la aplicación Vue de tu aplicación (es decir, no tus rutas de Nitro)
Siempre que sea posible, las reglas de ruta se aplicarán automáticamente a las reglas nativas de la plataforma de despliegue para un rendimiento óptimo (actualmente se soportan Netlify y Vercel).
Ten en cuenta que el Renderizado Híbrido no está disponible cuando se usa nuxt generate
.
Ejemplos:
Renderizado del Lado del Borde
El Renderizado del Lado del Borde (ESR) es una característica poderosa introducida en Nuxt que permite el renderizado de tu aplicación Nuxt más cerca de tus usuarios a través de servidores de borde de una Red de Entrega de Contenido (CDN). Al aprovechar ESR, puedes asegurar un mejor rendimiento y reducir la latencia, proporcionando así una experiencia de usuario mejorada.
Con ESR, el proceso de renderizado se lleva al 'borde' de la red - los servidores de borde del CDN. Ten en cuenta que ESR es más un objetivo de despliegue que un modo de renderizado real.
Cuando se realiza una solicitud para una página, en lugar de ir todo el camino hasta el servidor original, es interceptada por el servidor de borde más cercano. Este servidor genera el HTML para la página y lo envía de vuelta al usuario. Este proceso minimiza la distancia física que los datos tienen que recorrer, reduciendo la latencia y cargando la página más rápido.
El renderizado del lado del borde es posible gracias a Nitro, el motor de servidor que impulsa Nuxt. Ofrece soporte multiplataforma para Node.js, Deno, Cloudflare Workers, y más.
Las plataformas actuales donde puedes aprovechar ESR son:
- Cloudflare Pages con configuración cero usando la integración git y el comando
nuxt build
- Vercel Edge Functions usando el comando
nuxt build
y la variable de entornoNITRO_PRESET=vercel-edge
- Netlify Edge Functions usando el comando
nuxt build
y la variable de entornoNITRO_PRESET=netlify-edge
Ten en cuenta que el Renderizado Híbrido puede usarse cuando se utiliza el Renderizado del Lado del Borde con reglas de ruta.
Puedes explorar ejemplos de código abierto desplegados en algunas de las plataformas mencionadas anteriormente:
※Esta página es una traducción no oficial de la documentación oficial de Nuxt.js.
La página correspondiente en la documentación oficial está aquí:
https://nuxt.com/docs/3.x/guide/concepts/rendering