Demo
Página de demostración
¿Qué es SSR?
Esta página demo no es una utilidad final para usuarios, sino una pequeña ruta de referencia para renderizado del lado del servidor. Muestra cómo una página de Next.js App Router puede obtener datos en el servidor, insertar el resultado en el primer HTML y cargar las traducciones del locale actual. Por eso sirve para comprobar infraestructura compartida: variables de entorno, peticiones firmadas del servidor, forma de la respuesta API, enrutamiento por locale y carga de traducciones. Si esta página funciona, el camino básico de SSR está sano antes de depurar una herramienta más compleja. Si falla, el problema probablemente está en la configuración común del servidor o en la conectividad con la API. Debe mantenerse simple para seguir siendo una prueba rápida tras despliegues o cambios de framework.
Cómo usar
Cómo usar
- La página llama automáticamente a la API del backend
- El HTML incluye contenido pre-renderizado, sin necesidad de solicitud del cliente
- Consulta los datos devueltos por la API
- Ideal para páginas que necesitan optimización SEO
Notas de desarrollo
- Usa esta página como prueba de humo para SSR, carga de localización, solicitudes firmadas al servidor y conectividad con la API.
- Si esta página falla, revisa la configuración compartida del servidor antes de depurar una página de herramienta específica.
Casos de uso
Principio técnico
Esta página Demo está construida sobre Next.js 16 App Router y usa renderizado del lado del servidor (SSR) por defecto. Cuando un usuario solicita la página, el servidor Node.js primero ejecuta el componente React, llama a la API del backend para obtener datos y devuelve el HTML completamente renderizado al navegador en una única respuesta. El navegador comienza a analizar y pintar el HTML de inmediato, por lo que los usuarios ven el contenido completo en el primer fotograma sin esperar a que el JavaScript se descargue y ejecute. Esto contrasta fuertemente con el renderizado del lado del cliente (CSR) tradicional. Con CSR, el servidor solo devuelve un shell HTML casi vacío y un enlace a JS; el navegador tiene que descargar el paquete JS, ejecutar la inicialización del framework, llamar a las APIs para obtener datos y solo entonces renderizar la página. Desde la perspectiva del usuario es 'una pantalla en blanco durante un rato', y es aún peor para los rastreadores de buscadores: la mayoría no ejecutan JavaScript y solo ven el shell vacío. Tras el SSR, Next.js también inyecta un fragmento de JavaScript para realizar la 'hidratación': asociar el DOM existente con el árbol de componentes React y vincular los listeners de eventos para que la página se vuelva interactiva. El flujo completo es: análisis HTML -> carga CSS -> descarga JS -> hidratación -> página interactiva. Entre las tres Core Web Vitals, LCP (Largest Contentful Paint) y CLS (Cumulative Layout Shift) suelen ser mejores con SSR, mientras que INP (Interaction to Next Paint) depende de la velocidad de hidratación y la calidad de implementación de los manejadores de eventos.
- Next.js App Router: las páginas del App Router son Server Components por defecto, se ejecutan en el servidor y devuelven HTML automáticamente sin configuración adicional.
- SSR vs CSR: SSR ofrece un primer pintado rápido y compatibilidad con SEO a costa de recursos del servidor; CSR se adapta a paneles internos y otros escenarios interactivos que no necesitan SEO.
- Flujo del primer pintado: análisis HTML -> carga y renderizado CSS -> descarga y ejecución JS -> hidratación React -> página interactiva; cada paso afecta al LCP.
- Compatibilidad con rastreo SEO: los rastreadores principales como Googlebot y Bingbot leen el texto HTML directamente; la salida SSR con contenido completo garantiza cobertura de rastreo.
- Umbrales de Web Vitals: LCP < 2,5 s, INP < 200 ms, CLS < 0,1 son los umbrales recomendados como 'buenos' por Google; SSR facilita alcanzar LCP y CLS.
- Solicitudes firmadas: la página Demo llama a la API del backend a través de serverApiFetch en el servidor, portando automáticamente X-Timestamp, X-Nonce y X-Sign para completar la autenticación.
Ejemplos
SSR (renderizado del lado del servidor)
// app/page.tsx (Server Component por defecto)
export default async function Page() {
const data = await fetch('/api/info').then(r => r.json());
return <div>{data.title}</div>;
}
// El HTML ya contiene directamente <div>contenido real</div>CSR (renderizado del lado del cliente)
'use client';
import { useEffect, useState } from 'react';
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/info').then(r => r.json()).then(setData);
}, []);
return <div>{data?.title || 'Loading...'}</div>;
}
// El HTML del primer pintado solo contiene <div>Loading...</div>Comparación de velocidad del primer pintado
# SSR
FCP: 0.4s LCP: 0.8s TTI: 1.2s
SEO: los rastreadores obtienen el contenido completo directamente
# CSR
FCP: 0.6s LCP: 1.8s TTI: 2.4s
SEO: los rastreadores deben ejecutar JS para obtener el contenidoPreguntas frecuentes
¿Qué demuestra realmente esta página de demostración?
Es una ruta de referencia con renderizado en servidor (SSR) que muestra cómo una página del App Router de Next.js puede obtener datos en el servidor, incrustarlos en la primera respuesta HTML y, aun así, cargar los textos localizados correctos. No es una utilidad para usuarios finales: es una prueba de humo para desarrolladores.
¿Los datos se obtienen en el servidor o en el navegador?
En el servidor. La página llama a serverApiFetch (con las cabeceras firmadas de src/lib/sign.ts) dentro del React Server Component, así que el navegador recibe un HTML que ya contiene los datos. No hay fetch desde el cliente en la primera carga.
¿Por qué la página muestra a veces datos obsoletos?
Next.js puede cachear la respuesta SSR según la configuración de revalidate. Si necesitas datos frescos en cada solicitud, indica 'export const dynamic = "force-dynamic"' o pasa {cache: 'no-store'} al fetch. La ruta de demo usa el comportamiento por defecto para mantener el ejemplo simple.
¿Puedo copiar este patrón para mi propia página?
Sí, esa es la idea. La ruta muestra cómo combinar getTranslations de next-intl con un fetch en el servidor y pasar el resultado a un Client Component para la interactividad. Copia layout.tsx y page.tsx y sustituye la fuente de datos.
¿Por qué necesito firmar las solicitudes para una API interna?
X-Timestamp / X-Nonce / X-Sign bloquean ataques de replay y aseguran que las solicitudes que llegan desde la web pública provengan realmente de un cliente confiable. La clave de firma es por sesión para usuarios autenticados y un valor por defecto en el resto de casos; consulta src/lib/sign.ts y src/lib/fetch.ts para la implementación.
¿Esta página existirá en las builds de producción?
Forma parte de la app desplegada como referencia, pero no está enlazada desde la página de inicio ni desde la lista de herramientas, ni se anuncia como herramienta de cara al usuario. Tómala como documentación para desarrolladores renderizada en forma de ruta.
¿Qué debería revisar si quiero entender la estructura del proyecto?
Empieza por el layout.tsx y el page.tsx de esta página y luego lee src/i18n.ts (configuración de idiomas), src/i18n/request.ts (carga global de traducciones), src/lib/load-page-messages.ts (traducciones por página) y src/lib/fetch.ts (envoltorios de solicitudes firmadas).