W 2026 oba routery są nadal wspierane, ale większość nowych możliwości Next.js trafia najpierw do App Router. W tym artykule porównam oba rozwiązania bez marketingowego szumu i pokażę nie tylko zalety, ale też realny koszt migracji, granice ekosystemu i momenty, w których Pages Router wciąż bywa rozsądnym wyborem.
App Router vs Pages Router: szybkie porównanie
| Kryterium | Pages Router | App Router |
|---|---|---|
| Folder | pages/ | app/ |
| Model komponentów | strony hydratowane po stronie klienta | Server Components domyślnie, jawne granice klienta |
| Pobieranie danych | getServerSideProps, getStaticProps | async Server Components i funkcje danych |
| Layouty | _app.tsx i opcjonalny getLayout | natywne, zagnieżdżone, zachowujące stan |
| Loading i błędy | własne komponenty i obsługa routera | loading.tsx, error.tsx, Suspense |
| Metadata | next/head | Metadata API i generateMetadata |
| JavaScript klientowy | cały moduł strony podlega hydratacji | zależy od granic 'use client' |
| Streaming tras | brak natywnego modelu segmentów | wbudowany z Suspense |
| Status | wspierany | rekomendowany dla najnowszych funkcji |
| Krzywa uczenia | niższa dla znających klasyczny React | wyższa przez RSC, cache i granice środowisk |
Czym różni się App Router od Pages Router?
Zanim przejdziemy do szczegółów, warto zwrócić uwagę na fundamentalną różnicę:
Pages Router to tradycyjny routing Next.js, w którym pliki w folderze pages/ automatycznie stają się trasami. Strony mogą być prerenderowane przez , lub ISR, ale kod komponentu strony jest wysyłany do przeglądarki i hydratowany. Określenie „Client Component” należy przede wszystkim do modelu RSC używanego w App Routerze.
App Router opiera się na komponentach serwerowych z biblioteką React Server Components i routingu w folderze app/. Domyślnie wszystkie komponenty to Server Components, a layouts, loading states i error boundaries są wbudowane w strukturę folderów.
Kluczowe różnice między App Router i Pages Router
1. Pobieranie danych w App Router i Pages Router
Tutaj zaszła największa zmiana i jest to też źródło największych komplikacji.
Pages Router korzysta z dedykowanych funkcji eksportowanych z komponentu strony:
App Router pobiera dane bezpośrednio w komponencie:
W Next.js 16 params i searchParams stron są Promise. generateStaticParams() dostarcza znane parametry do prerenderowania, ale nie zastępuje decyzji o cache i obsłudze nieznanych ścieżek.
Model cache zależy od konfiguracji projektu. Bez Cache Components wywołania fetch() nie są domyślnie cache'owane; cache włączasz przez cache: 'force-cache' lub rewalidację. Opcjonalne cacheComponents: true w Next.js 16 udostępnia model oparty na 'use cache', cacheLife i cacheTag. Przed migracją ustal jeden model i opisz go w zasadach projektu, żeby zespół świadomie odróżniał dane świeże, cache'owane i unieważniane po mutacji.
2. Layouty w App Router i Pages Router
Pages Router ma jeden globalny _app.tsx i opcjonalnie per-page layouts przez pattern z getLayout:
App Router ma layouty natywne, zagnieżdżone i zachowujące stan:
Layouty w App Router mogą zachowywać stan i nie być odtwarzane przy każdej nawigacji w obrębie tego samego drzewa. To ogromna różnica dla , ale tylko wtedy, gdy sensownie zaprojektujesz granice layoutów i nie przeniesiesz zbyt wiele logiki do Client Components.
3. Loading i error states w routingu Next.js
Pages Router nie ma segmentowych konwencji loading i error. Dane z getServerSideProps lub getStaticProps są gotowe przed renderowaniem strony, natomiast stan przejścia klientowego trzeba obsłużyć przez zdarzenia routera, bibliotekę danych albo własny komponent. Błędy można przechwytywać przez _error.tsx, error boundary lub obsługę właściwą dla konkretnego źródła danych.
App Router integruje loading i error boundaries ze strukturą tras:
loading.tsx automatycznie tworzy granicę Suspense dla strony i jej potomków oraz zapewnia natychmiastowy fallback podczas nawigacji. error.tsx musi być Client Componentem i przechwytuje błędy zagnieżdżone poniżej granicy, ale nie błąd layoutu z tego samego segmentu. Dla root layoutu służy global-error.tsx.
4. Server Components vs Client Components
W Pages Router kod komponentu strony jest hydratowany w przeglądarce, nawet jeśli HTML powstał przez SSR lub SSG. Import używany podczas renderowania komponentu może więc trafić do klientowego bundla. Kod wykorzystywany wyłącznie w getStaticProps albo getServerSideProps jest usuwany z bundla klienta.
App Router domyślnie używa Server Components, więc kod zostaje na serwerze:
Może to zmniejszyć JavaScript wysyłany do przeglądarki, ale nie robi tego automatycznie. Dyrektywa 'use client' wyznacza granicę modułów: importy i komponenty poniżej tej granicy należą do klientowego grafu. Najlepszy efekt daje pozostawienie dużej części strony na serwerze i wydzielenie małych, interaktywnych komponentów.
5. Metadata i SEO w App Router i Pages Router
Pages Router używa komponentu Head lub next/head:
App Router używa Metadata API z pełnym typowaniem:
Metadata API obsługuje statyczny obiekt metadata, dynamiczną funkcję generateMetadata oraz specjalne pliki dla ikon, Open Graph, sitemap i robots. Eksporty metadanych działają wyłącznie w Server Components. Nie daje to App Routerowi automatycznej przewagi SEO nad poprawnie wyrenderowaną stroną Pages Routera, ale centralizuje konfigurację i typowanie.
Wydajność App Router vs Pages Router
| Aspekt | Pages Router | App Router |
|---|---|---|
| JavaScript klientowy | graf modułów strony | graf poniżej granic 'use client' |
| hydratacja drzewa strony | hydratacja Client Components i uzgodnienie RSC | |
| Streaming segmentów | brak natywnej konwencji | Suspense i loading.tsx |
| Trwałe layouty | własny getLayout i stan aplikacji | natywne layouty zachowujące stan |
| Cache | SSG, ISR, SSR i cache danych | cache danych, tras lub Cache Components |
App Router daje więcej narzędzi do ograniczania JavaScriptu i progresywnego renderowania, ale wynik zależy od architektury. Duży layout oznaczony 'use client' może zniwelować przewagę RSC, a dobrze zbudowana strona SSG w Pages Routerze może mieć bardzo dobre LCP. Porównuj rozmiar JavaScriptu, TTFB, LCP, INP, liczbę requestów i zachowanie nawigacji, nie samą nazwę routera.
Problemy App Routera, które warto znać przed wyborem
App Router nie zawsze jest idealnym rozwiązaniem dla każdego zespołu i w każdej sytuacji. Przed wyborem uwzględnij:
- Rozróżnienie kodu serwerowego od klienckiego: trudności w odróżnieniu kodu serwerowego od klienta, czyli która część kodu działa na serwerze, a która w przeglądarce. Jest to szczególnie problematyczne, gdy używasz bibliotek, które potrzebują dostępu do funkcji przeglądarki (np.
window) lub specjalnych funkcji Reacta (hooków), które działają tylko po stronie klienta. - Dwa modele cache w Next.js 16: zespół musi wiedzieć, czy projekt używa Cache Components, i dobrać do tego
fetch,'use cache', rewalidację oraz invalidację po mutacji. - Testowanie komponentów serwerowych: część przypadków można testować integracyjnie, ale złożone przepływy RSC, streaming i granice routera warto pokryć testami E2E. Nie oznacza to rezygnacji z testów jednostkowych dla czystej logiki.
- Nowe koncepcje: Server Components, serializowalne propsy, streaming, Server Actions i granice środowisk wymagają czasu na naukę oraz przeglądu używanych bibliotek.
Kiedy wybrać Pages Router w projekcie Next.js?
- utrzymujesz stabilny projekt i nie potrzebujesz funkcji App Routera,
- koszt regresji przewyższa spodziewaną korzyść migracji,
- kluczowe biblioteki, niestandardowy
_documentalbo model providerów wymagają najpierw przebudowy, - zespół nie ma jeszcze testów chroniących logowanie, płatności i krytyczne formularze,
- musisz dostarczyć funkcję biznesową, a migrację możesz zaplanować jako osobny projekt techniczny.
„Prosta strona” nie jest sama w sobie argumentem za Pages Routerem. Dla nowego landing page'a App Router również będzie prostym i aktualnym wyborem.
Kiedy wybrać App Router w projekcie Next.js?
- zaczynasz nowy projekt i chcesz korzystać z aktualnego modelu Next.js,
- chcesz pobierać dane w Server Components i ograniczyć klientowy graf modułów,
- potrzebujesz zagnieżdżonych layoutów, streamingu lub progresywnych stanów ładowania,
- planujesz formularze i mutacje oparte na Server Actions,
- chcesz używać Metadata API, Route Handlers albo opcjonalnych Cache Components.
SEO nie powinno samodzielnie rozstrzygać wyboru. Oba routery mogą wygenerować indeksowalny HTML, poprawne linki kanoniczne, sitemapę i dane strukturalne. App Router oferuje wygodniejsze API, nie automatycznie lepsze pozycje.
Czy można używać App Router i Pages Router w jednym projekcie?
Foldery pages/ i app/ mogą współistnieć, co pozwala migrować kolejne URL-e oddzielnie.
Ta sama trasa nie może istnieć w obu folderach, ponieważ spowoduje konflikt podczas budowania aplikacji. Jest też ważny koszt hybrydy: przejście między URL-em obsługiwanym przez Pages Router i URL-em App Routera wykonuje pełną nawigację dokumentu. Automatyczny prefetch next/link nie działa pomiędzy routerami, a pamięć klientowa poza trwałym storage zostaje zresetowana.
Podczas migracji nadal utrzymuj _app.tsx i _document.tsx dla starych tras. Root layout z app/ ich nie opakowuje, a globalne style zaimportowane tylko w app/layout.tsx nie obejmą stron z pages/.
Migracja z Pages Router do App Router
Bezpieczna kolejność migracji wygląda następująco:
- Zaktualizuj wspólne API, takie jak
Image,Link,Scripti wersje Reacta, jeszcze przed przenoszeniem tras. - Utwórz root layout i przenieś odpowiednie elementy
_apporaz_document, pozostawiając stare pliki dla Pages Routera. - Wydziel providery do Client Componentu, ponieważ React Context nie działa bezpośrednio w Server Componentach.
- Przenieś statyczną trasę pilotażową i sprawdź style, metadata, analitykę oraz nawigację do obu routerów.
- Zmień hooki routingu:
next/routerzastąp przezuseRouter,usePathname,useSearchParamslubuseParamsznext/navigation. - Migruj dane świadomie: osobno odwzoruj SSR, SSG, ISR, fallbacki i invalidację cache zamiast mechanicznie usuwać
getStaticProps. - Zostaw
pages/apialbo przenieś wybrane endpointy do Route Handlers. Nie zamieniaj endpointu na Server Component, jeśli korzystają z niego inne klienty. - Uruchom testy E2E i pomiary wydajności przed przeniesieniem kolejnej grupy tras.
Najłatwiejszym pierwszym krokiem dla złożonej strony jest przeniesienie jej dotychczasowego komponentu do pliku z 'use client' i wyrenderowanie go z nowego Server Componentu page.tsx. Dopiero później przesuwaj pobieranie danych i statyczne fragmenty na serwer. Dzięki temu migracja zmienia jedną granicę naraz.
App Router czy Pages Router: moja rekomendacja
Nowy projekt w 2026? Zacznij od App Routera, chyba że konkretna zależność lub wymaganie platformowe wymusza Pages Router. To ścieżka rekomendowana w aktualnej dokumentacji dla najnowszych funkcji React i Next.js.
Istniejący projekt? Najpierw wykonaj audyt. Zostań przy Pages Router, jeśli działa, a migracja nie ma mierzalnego celu. Migruj, gdy uprości layouty i dane, ograniczy JavaScript, ułatwi rozwój albo odblokuje konkretną funkcję. Sam status „nowszego routera” nie uzasadnia ryzyka regresji.
Uczysz się Next.js? Zacznij od App Routera i jego modelu routingu, renderowania oraz pobierania danych. Pages Router nadal warto rozumieć, ponieważ wiele istniejących projektów go używa, ale nowe funkcje poznawaj przede wszystkim w modelu App Router.


