Interfaz de carga y transmisión en flujo (Streaming)

El archivo especial loading.js te ayuda a crear una interfaz de carga significativa con React Suspense. Con esta convención, puedes mostrar un estado de carga instantáneo desde el servidor mientras se carga el contenido de un segmento de ruta. El nuevo contenido se intercambia automáticamente una vez que se completa el renderizado.

Interfaz de carga

Estados de carga instantáneos

Un estado de carga instantáneo es una interfaz de respaldo que se muestra inmediatamente al navegar. Puedes pre-renderizar indicadores de carga como esqueletos (skeletons) y spinners, o una pequeña pero significativa parte de las pantallas futuras como una foto de portada, título, etc. Esto ayuda a los usuarios a entender que la aplicación está respondiendo y proporciona una mejor experiencia de usuario.

Crea un estado de carga añadiendo un archivo loading.js dentro de una carpeta.

Archivo especial loading.js
export default function Loading() {
  // Puedes añadir cualquier interfaz dentro de Loading, incluyendo un Skeleton.
  return <LoadingSkeleton />
}
export default function Loading() {
  // Puedes añadir cualquier interfaz dentro de Loading, incluyendo un Skeleton.
  return <LoadingSkeleton />
}

En la misma carpeta, loading.js se anidará dentro de layout.js. Envolverá automáticamente el archivo page.js y cualquier hijo en un límite <Suspense>.

Resumen de loading.js

Es bueno saber:

  • La navegación es inmediata, incluso con enrutamiento centrado en el servidor.
  • La navegación es interrumpible, lo que significa que cambiar de ruta no necesita esperar a que el contenido de la ruta se cargue completamente antes de navegar a otra ruta.
  • Los diseños compartidos permanecen interactivos mientras se cargan los nuevos segmentos de ruta.

Recomendación: Usa la convención loading.js para segmentos de ruta (diseños y páginas) ya que Next.js optimiza esta funcionalidad.

Transmisión en flujo (Streaming) con Suspense

Además de loading.js, también puedes crear manualmente límites de Suspense para tus propios componentes de interfaz. El App Router admite transmisión en flujo con Suspense tanto para entornos de ejecución Node.js y Edge.

¿Qué es la transmisión en flujo (Streaming)?

Para entender cómo funciona la transmisión en flujo en React y Next.js, es útil comprender el Renderizado del lado del servidor (SSR) y sus limitaciones.

Con SSR, hay una serie de pasos que deben completarse antes de que un usuario pueda ver e interactuar con una página:

  1. Primero, todos los datos para una página determinada se obtienen en el servidor.
  2. Luego, el servidor renderiza el HTML para la página.
  3. El HTML, CSS y JavaScript de la página se envían al cliente.
  4. Se muestra una interfaz de usuario no interactiva usando el HTML generado y el CSS.
  5. Finalmente, React hidrata la interfaz de usuario para hacerla interactiva.
Gráfico mostrando el renderizado del servidor sin transmisión en flujo

Estos pasos son secuenciales y bloqueantes, lo que significa que el servidor solo puede renderizar el HTML de una página una vez que se han obtenido todos los datos. Y, en el cliente, React solo puede hidratar la interfaz una vez que se ha descargado el código de todos los componentes de la página.

SSR con React y Next.js ayuda a mejorar el rendimiento de carga percibido al mostrar una página no interactiva al usuario lo antes posible.

Renderizado del servidor sin transmisión en flujo

Sin embargo, aún puede ser lento ya que toda la obtención de datos en el servidor debe completarse antes de que la página pueda mostrarse al usuario.

La transmisión en flujo te permite dividir el HTML de la página en fragmentos más pequeños y enviar esos fragmentos progresivamente desde el servidor al cliente.

Cómo funciona el renderizado del servidor con transmisión en flujo

Esto permite que partes de la página se muestren antes, sin esperar a que todos los datos se carguen antes de que se pueda renderizar cualquier interfaz.

La transmisión en flujo funciona bien con el modelo de componentes de React porque cada componente puede considerarse un fragmento. Los componentes que tienen mayor prioridad (por ejemplo, información del producto) o que no dependen de datos pueden enviarse primero (por ejemplo, el diseño), y React puede comenzar la hidratación antes. Los componentes con menor prioridad (por ejemplo, reseñas, productos relacionados) pueden enviarse en la misma solicitud del servidor después de que se hayan obtenido sus datos.

Gráfico mostrando el renderizado del servidor con transmisión en flujo

La transmisión en flujo es particularmente beneficiosa cuando deseas evitar que las solicitudes de datos largas bloqueen el renderizado de la página, ya que puede reducir el Tiempo hasta el primer byte (TTFB) y la Primera pintura con contenido (FCP). También ayuda a mejorar el Tiempo hasta interactivo (TTI), especialmente en dispositivos más lentos.

Ejemplo

<Suspense> funciona envolviendo un componente que realiza una acción asíncrona (por ejemplo, obtener datos), mostrando una interfaz de respaldo (por ejemplo, skeleton, spinner) mientras ocurre, y luego intercambiando tu componente una vez que se completa la acción.

import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (
    <section>
      <Suspense fallback={<p>Cargando feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Cargando clima...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}
import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (
    <section>
      <Suspense fallback={<p>Cargando feed...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>Cargando clima...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}

Al usar Suspense, obtienes los beneficios de:

  1. Renderizado del servidor con transmisión en flujo - Renderizado progresivo de HTML desde el servidor al cliente.
  2. Hidratación selectiva - React prioriza qué componentes hacer interactivos primero según la interacción del usuario.

Para más ejemplos y casos de uso de Suspense, consulta la Documentación de React.

SEO

  • Next.js esperará a que se complete la obtención de datos dentro de generateMetadata antes de transmitir la interfaz al cliente. Esto garantiza que la primera parte de una respuesta transmitida incluya las etiquetas <head>.
  • Dado que la transmisión en flujo se renderiza en el servidor, no afecta al SEO. Puedes usar la herramienta Mobile Friendly Test de Google para ver cómo aparece tu página para los rastreadores web de Google y ver el HTML serializado (fuente).

Códigos de estado

Al transmitir en flujo, se devolverá un código de estado 200 para indicar que la solicitud fue exitosa.

El servidor aún puede comunicar errores o problemas al cliente dentro del contenido transmitido, por ejemplo, al usar redirect o notFound. Dado que los encabezados de respuesta ya se han enviado al cliente, el código de estado de la respuesta no se puede actualizar. Esto no afecta al SEO.