proscinski.com

Jak dodać pasek postępu ładowania strony w Next.js App Router? Konfiguracja nextjs-toploader, dostosowanie kolorów i kiedy warto go użyć.

Next.js App Router domyślnie nie pokazuje żadnego wizualnego wskaźnika ładowania przy nawigacji między stronami. Użytkownik klika link i przez chwilę nic się nie dzieje – dopóki nowa strona się nie wyrenderuje. Na szybkim łączu to ułamek sekundy. Na wolniejszym, albo przy stronach z dynamicznym pobieraniem danych, to wystarczająco długo, żeby ktoś pomyślał, że strona nie działa.

Dlaczego to ważne

Brak wizualnego feedbacku po kliknięciu to najczęstsza przyczyna podwójnych kliknięć i poczucia, że strona jest wolna – nawet jeśli technicznie ładuje się poprawnie.

Co to jest nextjs-toploader

nextjs-toploader to lekka biblioteka, która dodaje cienki pasek postępu na górze strony – taki sam, jaki znasz z YouTube, GitHuba czy Slacka. Pod spodem korzysta z NProgress, ale jest specjalnie zoptymalizowana pod Next.js App Router.

Paczka waży kilka kilobajtów, nie wymaga żadnej konfiguracji routera, nie dodaje żadnych zależności runtime i działa automatycznie z next/link oraz next/navigation. Wystarczy dodać jeden komponent do layoutu.

Instalacja

Jeden krok – instalacja paczki przez npm:

Instalacja nextjs-toploader
Bash
npm install nextjs-toploader

Konfiguracja w App Router

Dodaj komponent NextTopLoader do głównego layoutu (app/layout.tsx). Powinien znajdować się wewnątrz <body>, najlepiej jako pierwszy element – przed headerem i resztą strony.

app/layout.tsx – dodanie NextTopLoader
TypeScript
import NextTopLoader from "nextjs-toploader";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="pl">
      <body>
        <NextTopLoader color="#2563eb" showSpinner={false} />
        <header>{/* ... */}</header>
        <main>{children}</main>
      </body>
    </html>
  );
}

Dostępne opcje konfiguracji

Komponent przyjmuje kilka przydatnych propsów, dzięki którym dopasujesz go do swojego projektu:

  • color – kolor paska. Ustaw na główny kolor brandowy, np. #2563eb.
  • showSpinner – domyślnie true. Spinner w rogu strony jest zbędny i rozpraszający – zalecam ustawienie na false.
  • height – grubość paska w pikselach. Domyślnie 3. Dwa piksele wyglądają subtelniej.
  • crawlSpeed – jak szybko pasek posuwa się automatycznie (w ms). Domyślnie 200.
  • speed – czas animacji ukrywania paska po załadowaniu (w ms). Domyślnie 200.
  • easing – funkcja przejścia CSS, np. ease lub ease-in-out.
  • shadow – cień pod paskiem. Można wyłączyć ustawiając na false dla bardziej minimalistycznego wyglądu.
  • zIndex – z-index paska. Domyślnie 1600 – wystarczająco wysoko, żeby był nad wszystkim.
Przykład pełnej konfiguracji
TypeScript
<NextTopLoader
  color="#2563eb"
  height={2}
  showSpinner={false}
  shadow={false}
  crawlSpeed={300}
  speed={200}
  easing="ease"
/>

Dopasowanie do dark mode

Jeśli Twoja strona obsługuje ciemny motyw, możesz przekazać kolor jako zmienną CSS. W ten sposób pasek automatycznie zmieni kolor razem z resztą interfejsu:

Kolor paska z zmiennej CSS
TypeScript
<NextTopLoader color="var(--primary)" showSpinner={false} />

Warunek: zmienna --primary musi być zdefiniowana w CSS zarówno dla jasnego, jak i ciemnego motywu.

Czy warto dodać pasek postępu?

Krótka odpowiedź: tak, prawie zawsze. Dłuższa odpowiedź poniżej.

Kiedy warto

  • Strona ma podstrony z dynamicznym pobieraniem danych (np. blog, realizacje, podstrony ofertowe z CMS-a).
  • Nawigacja między stronami trwa dłużej niż 100–200 ms – użytkownik potrzebuje wizualnego potwierdzenia, że coś się dzieje.
  • Chcesz, żeby strona czuła się jak aplikacja, a nie jak klasyczna witryna, która ładuje się od zera przy każdym kliknięciu.
  • Zależy Ci na profesjonalnym odbiorze – pasek postępu to detal, który odróżnia dopracowaną stronę od szablonowej.

Kiedy nie jest potrzebny

  • Strona jest w pełni statyczna (SSG), bez żadnych dynamicznych podstron – nawigacja jest natychmiastowa.
  • Masz własny system loading states oparty na React Suspense z komponentami loading.tsx na każdej podstronie.

Uwagi przy budowaniu w Dockerze

Jeśli budujesz aplikację Next.js w kontenerze Docker z osobnym named volume na node_modules (typowe w setupach z docker-compose na potrzeby hot-reload), samo docker compose up --build może nie wystarczyć. Volume z poprzedniego builda przeżywa restart kontenerów i nie zawiera nowej paczki.

Rozwiązanie: usuń volume z zależnościami przed rebuildem:

Rebuild z czystym volume node_modules
Bash
# Usuń tylko volume z zależnościami (bez bazy danych)
docker compose down
docker volume rm <nazwa-projektu>_frontend_node_modules
docker compose up -d --build

W Dockerfile produkcyjnym, gdzie npm ci wykonuje się w warstwie budowania, wystarczy --no-cache:

Rebuild produkcyjny bez cache
Bash
docker compose -f docker-compose.prod.yml build --no-cache frontend
docker compose -f docker-compose.prod.yml up -d frontend

Podsumowanie

nextjs-toploader to jeden komponent, jedna linia importu i zero konfiguracji routera. Daje wizualny feedback, którego Next.js App Router nie dostarcza out of the box, a który użytkownicy znają i oczekują z każdej nowoczesnej aplikacji webowej.

Pięć minut na wdrożenie. Żadnych efektów ubocznych. Konkretna poprawa tego, jak strona się „czuje” przy nawigacji.

Chcesz wdrożyć podobną stronę albo poprawić SEO?

Pracuję lokalnie w Lublin i zdalnie w całej Polsce. Jeśli ten temat dotyczy Twojej strony, poniżej masz dwa sensowne następne kroki.

Główny landing dla firm usługowych, które chcą więcej telefonów i formularzy.

TelefonBezpłatna wycena