Componente loading.js en Next.js

El archivo loading.js (o loading.tsx) en Next.js 13+ con App Router te permite mostrar una interfaz de carga inmediata mientras la página o parte de ella se está resolviendo en el servidor. Es una pieza clave del Streaming y React Suspense integrados en Next.js.

¿Qué es loading.js?

  • Es un componente especial que Next.js renderiza automáticamente como fallback mientras se carga el contenido real de una ruta.
  • Se ubica dentro de una carpeta de segmento: app/segment/loading.js.
  • Puede existir a nivel global (app/loading.js) o por ruta específica (e.g. app/posts/loading.js).
  • Se renderiza en el servidor y se envía instantáneamente al navegador (mejora la percepción de velocidad sin JS adicional).
  Importante

loading.js funciona solo con el App Router. No está disponible en el Pages Router clásico (pages/).

¿Para qué se usa?

  • Para mostrar un spinner o skeleton mientras una ruta o componente tarda en responder.
  • Para segmentar la experiencia de carga: puedes tener un loading.js en cada nivel de tu árbol de rutas.
  • Para mejorar UX y Core Web Vitals al entregar contenido parcial inmediatamente.

Beneficios

  • Percepción de velocidad: el usuario ve algo al instante.
  • Menos JavaScript en cliente: el fallback viene del servidor.
  • Control por segmentos: puedes definir la experiencia de carga por cada sección.
  • Se integra con Suspense/Streaming: no necesitas configurar manualmente Suspense para cada caso.

Ejemplo 1: Loading Global

Coloca un loading.js en la raíz de app/ para que toda la app tenga un fallback mientras se resuelve.

javascript
// app/loading.js
export default function Loading() {
return (
  <div style={{ display: 'grid', placeItems: 'center', minHeight: '60vh' }}>
    <p>Cargando contenido...</p>
  </div>
)
}

Ejemplo 2: Loading por Ruta

Un loading.js dentro de una carpeta de ruta aplica solo a esa sección.

javascript
// app/posts/loading.js
export default function Loading() {
return <p>Cargando posts...</p>
}

// app/posts/page.js
export default async function PostsPage() {
// Simula una carga lenta (1.5s)
await new Promise(resolve => setTimeout(resolve, 1500));
return (
  <section>
    <h1>Posts</h1>
    <ul>
      <li>Post 1</li>
      <li>Post 2</li>
    </ul>
  </section>
)
}

Ejemplo 3: Loading Anidado

Puedes tener loading.js en distintos niveles para definir fallbacks más precisos.

javascript
// app/dashboard/loading.js
export default function LoadingDashboard() {
return <p>Cargando dashboard...</p>
}

// app/dashboard/users/loading.js
export default function LoadingUsers() {
return <p>Cargando usuarios...</p>
}

Buenas Prácticas

  • Mantén el fallback ligero: evita lógica pesada; ideal un spinner o skeleton simple.
  • Usa skeletons si conoces la estructura: barras grises y bloques simulando el contenido real.
  • Server Component por defecto: loading.js se renderiza en servidor; si necesitas interactividad, añade "use client".
  • Consistencia visual: reutiliza un estilo de loading para toda la app.
  • Pruebas: usa setTimeout o await fetch(...) con retraso para validar que el fallback aparece.
javascript
// app/products/page.js
export default async function ProductsPage() {
// Simula una operación lenta
await new Promise(r => setTimeout(r, 2000));
return <div>Productos listos</div>
}

// app/products/loading.js
export default function Loading() {
return <p>Cargando productos...</p>
}
  Tip

Si necesitas interactividad dentro de loading.js (por ejemplo, un cancel button), agrega "use client" al inicio. En la mayoría de casos, no es necesario.

Errores comunes

  • Colocar loading.js en Pages Router (pages/) → No funciona.
  • Nombrar el archivo como Loading.js o loader.js → Debe ser exactamente loading.js/loading.tsx.
  • Fallback demasiado cargado (mucha lógica/JS) → Degrada el propósito del loading inmediato.

Checklist Rápido

5Guía rápida
  • Crea app/loading.js para fallback global.
  • Crea app/segment/loading.js para fallback por ruta.
  • Prueba con una carga lenta en page.js para validar.
  • Usa skeletons en vez de spinners cuando aplique.
  • Mantén el fallback simple y ligero.

Con loading.js, Next.js te ayuda a entregar una experiencia instantánea mientras el contenido real se prepara en el servidor, sin necesidad de JavaScript adicional en el cliente.