Saltar al contenido

¿Cómo integrar NProgress con Next.js?

Snippets para mostrar una barra de progreso en la parte superior mientras Next.js navega entre páginas, usando NProgress y los eventos del router.

1 min de lectura
  • react
  • next.js
  • snippets

Este artículo se escribió en 2021 para Next.js con Pages Router. Si tu proyecto está en App Router (Next.js 13+), router.events ya no existe; conviene migrar a nextjs-toploader o aprovechar loading.tsx + Suspense. Los snippets de abajo siguen siendo válidos para proyectos legados con Pages Router.

Si has usado Next.js, seguro notaste que la navegación entre páginas no siempre es instantánea: el router necesita un momento para descargar la data de la página destino. Para no dejar al usuario adivinando si algo está pasando, una barra de carga arriba es una solución clásica y de bajo costo.

A continuación, los pasos para integrar NProgress con Next.js (Pages Router).

1. Instalar NProgress

pnpm add nprogress
pnpm add -D @types/nprogress

2. Conectarlo a los eventos del router en _app.tsx

import * as React from 'react';
 
import type { AppProps } from 'next/app';
import { useRouter } from 'next/router';
import NProgress from 'nprogress';
 
function MyApp({ Component, pageProps }: AppProps) {
  const router = useRouter();
 
  React.useEffect(() => {
    const handleStart = () => NProgress.start();
    const handleStop = () => NProgress.done();
 
    router.events.on('routeChangeStart', handleStart);
    router.events.on('routeChangeComplete', handleStop);
    router.events.on('routeChangeError', handleStop);
 
    return () => {
      router.events.off('routeChangeStart', handleStart);
      router.events.off('routeChangeComplete', handleStop);
      router.events.off('routeChangeError', handleStop);
    };
  }, [router]);
 
  return <Component {...pageProps} />;
}
 
export default MyApp;

3. Dar estilo a la barra y al spinner

/* globals.css */
 
#nprogress {
  pointer-events: none;
}
 
#nprogress .bar {
  background: rgba(167, 139, 250, 0.8);
  position: fixed;
  z-index: 1031;
  top: 0;
  left: 0;
  width: 100%;
  height: 4px;
}
 
/* glow al final de la barra */
#nprogress .peg {
  display: block;
  position: absolute;
  right: 0;
  width: 100px;
  height: 100%;
  box-shadow:
    0 0 10px rgba(167, 139, 250, 0.8),
    0 0 5px rgba(167, 139, 250, 0.8);
  opacity: 1;
  transform: rotate(3deg) translate(0, -4px);
}
 
/* Quita esta sección si no quieres el spinner */
#nprogress .spinner {
  display: block;
  position: fixed;
  z-index: 1031;
  top: 15px;
  right: 15px;
}
 
#nprogress .spinner-icon {
  width: 18px;
  height: 18px;
  box-sizing: border-box;
  border: solid 2px transparent;
  border-top-color: rgba(167, 139, 250, 0.8);
  border-left-color: rgba(167, 139, 250, 0.8);
  border-radius: 50%;
  animation: nprogress-spinner 400ms linear infinite;
}
 
@keyframes nprogress-spinner {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

Con esto deberías ver una barra violeta en la parte superior cada vez que el router cambia de ruta. Pequeño detalle, gran mejora de UX.

¡Gracias por leer!