StriveLab
Strony internetowe
Usługi
RealizacjeO mnieBlogPorozmawiajmy
PL
EN

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

Automatyzacja AI

Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.

QA & Automation

Testy automatyczne komponentów i E2E w Cypress.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

StriveLab
Strony internetowe
Usługi
RealizacjeO mnieBlogPorozmawiajmy
PL
EN

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

Automatyzacja AI

Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.

QA & Automation

Testy automatyczne komponentów i E2E w Cypress.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

Astro

Ultraszybkie projekty, łączące lekkość ze skalowalnością.

Next.js

Elastyczne i wydajne narzędzia dla biznesu, które dotrzymają kroku Twojemu rozwojowi.

React

Połączenie intuicyjności z wydajnością, które zapewnia bezproblemową skalowalność kodu.

SEO & Performance

Audyt techniczny i optymalizacja pod kątem SEO i GEO.

Automatyzacja AI

Bezpieczne automatyzacje procesów i agenci AI w n8n, Make i Claude.

QA & Automation

Testy automatyczne komponentów i E2E w Cypress.

Doradztwo produktowe

Połączenie perspektywy produktu, developera i marketingu w jednym miejscu

RealizacjeO mnieBlog
Porozmawiajmy
PL
EN

Nowoczesne strony internetowe dla firm, które myślą odważnie.

Przewiń do góry

Nazwa

StriveLab Maciej Sala

NIP

6772218995

REGON

524008527

E-mail

contact@strivelab.pl

Usługi główne
  • Tworzenie stron internetowych
  • Strony internetowe Next.js
  • Strony internetowe Astro
  • Strony internetowe React
Inne usługi
  • Usługi
  • SEO & Performance Sprint
  • QA & Stabilizacja
  • Konsultacje Product / Delivery
  • Automatyzacja Procesów AI
  • Aplikacje webowe Next.js
  • Współpraca ciągła
Strony
  • O mnie
  • Usługi
  • Realizacje
  • Blog

© 2026 StriveLab.pl

Polityka prywatności
Next.jsReact

App Router czy Pages Router — co wybrać?

App Router czy Pages Router w Next.js 16? Konkretne różnice, koszty migracji i praktyczne kryteria wyboru dla nowych oraz istniejących projektów.

OpublikujLinkedInFacebookWyślij
Autor
Maciej Sala
Opublikowano
23 grudnia 2025 09:35
Czytanie
7 min czytania
Aktualizacja
25 maja 2026 10:55

Next.js 13 wprowadził App Router, czyli nowy sposób budowania aplikacji oparty na React Server Components. Ale Pages Router nigdzie nie zniknął. Dwa routery, dwa podejścia, jedna decyzja do podjęcia na starcie projektu.

Artykuł w skrócie

  • App Router to domyślny wybór — nowe funkcje Next.js trafiają tu pierwsze; Vercel jasno sygnalizuje, że to kierunek na przyszłość
  • React Server Components — kluczowa różnica: komponenty domyślnie renderują się na serwerze, eliminując potrzebę API dla prostych danych
  • Pages Router wciąż działa — nie znika, jest stabilny i sprawdza się w utrzymaniu istniejących projektów bez presji migracji
  • Koegzystencja jest możliwa — oba routery można używać jednocześnie, co ułatwia stopniową, inkrementalną migrację
  • CSS-in-JS wymaga konfiguracji — styled-components i Emotion potrzebują Registry wrapperów; Tailwind i CSS Modules działają od razu
  • Nie migruj bez powodu — Pages Router w działającym projekcie produkcyjnym nie wymaga migracji dla samej migracji

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.

Notatka

Najgorszy powód migracji to samo poczucie, że „nowy router jest nowszy”. Najpierw nazwij konkretną korzyść: lepsze layouty, Server Components, streaming, prostsze pobieranie danych albo mniejszy koszt utrzymania.

Szybkie porównanie

KryteriumPages RouterApp Router
Folderpages/app/
Domyślny typ komponentuClient ComponentServer Component
Pobieranie danychgetServerSideProps, getStaticPropsasync component, fetch()
Layouty_app.tsx + getLayout patternNatywne, zagnieżdżone, zachowują stan
Loading/Error statesRęczna implementacjaPlik loading.tsx / error.tsx
Metadata / SEO, czyli Search Engine Optimization, to optymalizacja strony pod widoczność w wynikach wyszukiwania.next/headMetadata API, czyli Application Programming Interface, definiuje sposób komunikacji między aplikacjami lub modułami. Tu chodzi o konwencje plików Next.js, które zamieniają eksportowaną funkcję w gotowy plik sitemap.xml lub robots.txt. z TypeScript
Bundle to paczka JavaScriptu lub innych zasobów wysyłana do przeglądarki jako część aplikacji. sizeWiększy (cały kod do klienta)Mniejszy (Server Components)
StreamingBrakWbudowany z Suspense
Status wsparciaUtrzymywany, bez nowych funkcjiAktywny rozwój, nowe funkcje
Krzywa uczenia sięNiska dla znających ReactWyższa (RSC, Server Actions, cache)
Kiedy wybraćIstniejący projekt, proste strony, stabilnośćNowe projekty, dashboard, SSaaS, SEO-heavy

Czym się różnią?

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. Komponenty są Client Components z opcjonalnym SSR, czyli Server-Side Rendering, to generowanie HTML na serwerze przy żądaniu — komponent client:only je pomija i renderuje się wyłącznie w przeglądarce./SSG (Static Site Generation) to generowanie kompletnego HTML podczas budowania strony. Gotowe pliki serwujesz z CDN bez renderowania na żądanie — najszybszy i najtańszy model dla treści, która nie zmienia się przy każdej wizycie. przez getServerSideProps i getStaticProps.

App Router — kluczowe w nim są komponenty serwerowe z biblioteką React Server Components wy routing w folderze app/, omyślnie wszystkie komponenty to Server Components,a layouts, loading states i error boundaries są wbudowane w strukturę folderów.

Code
# Pages Router
pages/
├── index.tsx          → /
├── about.tsx          → /about
├── blog/
│   ├── index.tsx      → /blog
│   └── [slug].tsx     → /blog/:slug
└── _app.tsx           → wrapper dla wszystkich stron

# App Router
app/
├── page.tsx           → /
├── layout.tsx         → wrapper (dziedziczony)
├── about/
│   └── page.tsx       → /about
└── blog/
    ├── page.tsx       → /blog
    └── [slug]/
        └── page.tsx   → /blog/:slug

Kluczowe różnice

1. Pobieranie danych

Tutaj zaszła największa zmiana i jest to też źródło największych komplikacji

Pages Router — dedykowane funkcje eksportowane z komponentu strony:

Code
// pages/blog/[slug].tsx
export async function getStaticProps({ params }) {
  const post = await getPost(params.slug)
  return { props: { post } }
}
 
export async function getStaticPaths() {
  const posts = await getAllPosts()
  return {
    paths: posts.map((post) => ({ params: { slug: post.slug } })),
    fallback: false,
  }
}
 
export default function BlogPost({ post }) {
  return <article>{post.title}</article>
}

App Router — dane pobierasz bezpośrednio w komponencie:

Code
// app/blog/[slug]/page.tsx
async function BlogPost({ params }: { params: { slug: string } }) {
  const post = await getPost(slug)
  return <article>{post.title}</article>
}
 
export default BlogPost
 
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map((post) => ({ slug: post.slug }))
}

Model pobierania danych w App Router bywa prostszy na poziomie samego kodu, ale dochodzi nowa warstwa decyzji o cache, rewalidacji i granicach między kodem serwerowym, a klienckim. Jeśli interesuje Cię ten temat, możesz zobaczyć więcej o strategiach pobierania danych w artykule o fetch, cache i rewalidacji w Next.js.

2. Layouty

Pages Router — jeden globalny _app.tsx, opcjonalnie per-page layouts przez pattern z getLayout:

Code
// pages/_app.tsx
export default function App({ Component, pageProps }) {
  const getLayout = Component.getLayout || ((page) => page)
  return getLayout(<Component {...pageProps} />)
}
 
// pages/dashboard.tsx
Dashboard.getLayout = (page) => <DashboardLayout>{page}</DashboardLayout>

App Router — layouty są natywne, zagnieżdżone i zachowują stan:

Code
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }) {
  return (
    <div className="flex">
      <Sidebar />
      <main>{children}</main>
    </div>
  )
}
 
// app/dashboard/settings/layout.tsx
export default function SettingsLayout({ children }) {
  return (
    <div>
      <SettingsNav />
      {children}
    </div>
  )
}

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 UX, czyli User Experience, opisuje całe doświadczenie użytkownika podczas korzystania z produktu., ale tylko wtedy, gdy sensownie zaprojektujesz granice layoutów i nie przeniesiesz zbyt wiele logiki do Client Components.

3. Loading i Error States

Pages Router — musisz sam zaimplementować loading states, ponieważ error boundaries to dodatkowa konfiguracja:

Code
// pages/dashboard.tsx
import { useState, useEffect } from 'react'
 
export default function Dashboard() {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
 
  useEffect(() => {
    fetchData()
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false))
  }, [])
 
  if (loading) return <Skeleton />
  if (error) return <ErrorMessage />
  return <DashboardContent data={data} />
}

App Router — konwencja plików obsługuje to automatycznie:

Code
app/dashboard/
├── page.tsx        → główna treść
├── loading.tsx     → pokazywany podczas ładowania
├── error.tsx       → pokazywany przy błędzie
└── not-found.tsx   → pokazywany dla 404
Code
// app/dashboard/loading.tsx
export default function Loading() {
  return <Skeleton />
}
 
// app/dashboard/error.tsx
;('use client')
 
export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Coś poszło nie tak</h2>
      <button onClick={reset}>Spróbuj ponownie</button>
    </div>
  )
}

4. Server Components vs Client Components

W Pages Router komponenty są z natury klienckie. Oznacza to, że nawet po wyrenderowaniu strony na serwerze (SSR/SSG), ich kod JavaScript i tak jest wysyłany do przeglądarki:

Code
// pages/product.tsx
import { formatPrice } from 'heavy-library' // trafia do bundle'a
 
export default function Product({ product }) {
  return <p>{formatPrice(product.price)}</p>
}

App Router — domyślnie Server Components, kod zostaje na serwerze:

Code
// app/product/page.tsx
import { formatPrice } from 'heavy-library' // NIE trafia do bundle'a
 
export default async function Product({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const product = await getProduct(id)
  return <p>{formatPrice(product.price)}</p>
}

To przekłada się na mniejszy JavaScript wysyłany do przeglądarki.

5. Metadata i SEO

Pages Router — komponent Head lub next/head:

Code
// pages/about.tsx
import Head from 'next/head'
 
export default function About() {
  return (
    <>
      <Head>
        <title>O nas | Moja Strona</title>
        <meta name="description" content="Opis strony" />
        <meta property="og:title" content="O nas" />
      </Head>
      <main>...</main>
    </>
  )
}

App Router — Metadata API z pełnym typowaniem:

Code
// app/about/page.tsx
import { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'O nas | Moja Strona',
  description: 'Opis strony',
  openGraph: {
    title: 'O nas',
  },
}
 
export default function About() {
  return <main>...</main>
}

Metadata API jest czytelniejsze i obsługuje dynamiczne meta tagi bez dodatkowych bibliotek.

Porównanie wydajności

AspektPages RouterApp Router
Bundle sizeWiększy (cały kod do klienta)Mniejszy (Server Components)
Hydration to etap, w którym React podłącza logikę JavaScript do już wygenerowanego HTML-a w przeglądarce.Pełna hydratacjaSelektywna hydratacja
StreamingBrakWbudowany z Suspense
Layout persistenceWymaga obejściaNatywne
Initial loadSzybki (SSR/SSG)Szybki + streaming

Gdzie App Router nadal potrafi boleć

App Router nie zawsze jest idealnym rozwiązaniem dla każdego zespołu i w każdej sytuacji, dlatego też warto bym rozwinął kilka potencjalnych trudności:

  • 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.
  • Złożone zarządzanie danymi: Mechanizmy pamięci podręcznej (cache) i odświeżania danych są bardziej zaawansowane niż w Pages Router, ale też bardziej skomplikowane w obsłudze. Samo użycie fetch() do pobierania danych nie gwarantuje, że zawsze będziesz mieć aktualne informacje.
  • Wyzwania w testowaniu: Narzędzia do testowania i same testy wciąż mogą być problematyczne, zwłaszcza przy asynchronicznych komponentach serwerowych. Testy kompleksowe (E2E) są aktualnie bezpieczniejszym wyborem niż próba testowania wszystkiego testami jednostkowymi.
  • Konieczność nauki nowych koncepcji: Zespół musi przyswoić nowe koncepcje, takie jak React Server Components, strumieniowanie danych, akcje serwerowe i nowe sposoby zarządzania pamięcią podręczną. To wymaga czasu i zmiany sposobu myślenia, a to powoduje duży opór zespołu.

Kiedy wybrać Pages Router?

  • Istniejący projekt — migracja dużego projektu to relatywnie duży wysiłek,
  • Proste strony — landing page, portfolio bez zastosowania złożonej logiki,
  • Zespół nie zna App Routera — krzywa uczenia się jest realna,
  • Zależność od bibliotek — niektóre biblioteki nie wspierają jeszcze Server Components,
  • Stabilność — Pages Router jest pewny i bardzo przewidywalny.

Kiedy wybrać App Router?

  • Nowy projekt — w praktyce to domyślny wybór dla większości nowych aplikacji,
  • Złożone layouty — dashboard, panel admina, aplikacja SaaS,
  • SEO i wydajność — łatwiej wykorzystać streaming, Metadata API i nowy model renderowania,
  • Duże ilości danych — Server Components redukują bundle,
  • Streaming — potrzebujesz pokazywać treść progresywnie,

Pytanie brzmi - czy można używać obu?

Tak, jest taka możliwość, by w Next.js używać hybrydowego podejścia — pages/ i app/ mogą współistnieć, co ułatwia stopniową migrację. Właśnie taka stopniowa migracja, może nam oszczędzić sporo złym emocji, a jednocześnie osiągniemy swój cel.

Code
my-project/
├── app/              # nowe strony w App Router
│   ├── dashboard/
│   └── settings/
├── pages/            # legacy strony
│   ├── old-page.tsx
│   └── api/          # API routes (tylko w pages/)

Uwaga! Pamiętaj, że ta sama trasa nie może istnieć w obu folderach (!)

Migracja z Pages Router do App Router

Jeśli masz istniejący projekt, migruj stopniowo:

  1. Utwórz folder app/ i skonfiguruj podstawowy layout.
  2. Zacznij od prostych stron, na "tapetę" weź strony np. about, kontakt, statyczne treści.
  3. Migruj strony z danymi — zamień getStaticProps na komponenty serwerowe async.
  4. Zostaw API routes w pages/api/ albo migruj stopniowo do Route Handlers w app/**/route.ts.
  5. Na końcu migruj te najbardziej złożone strony, czyli dashboardy czy skomplikowane formularze etc.

Nie musisz migrować wszystkiego naraz. Hybrydowe podejście jest w pełni wspierane.

Moja rekomendacja

Nowy projekt w 2026? Najlepszy wybór to właśnie App Router, ponieważ to kierunek rozwoju Next.js i domyślna ścieżka w aktualnej dokumentacji.

Istniejący projekt? Najlepiej zostań przy Pages Router, jeśli działa i zespół nie potrzebuje funkcji specyficznych dla App Router. Nie migruj na siłę, tylko wtedy, gdy realnie uprości to architekturę albo odblokuje nowe możliwości. Z czasem różnica będzie bardziej widoczna między App Router i Pages Router.

Uczysz się Next.js? Zacznij od App Router i jego modelu routingu, renderowania oraz pobierania danych. Pages Router nadal warto rozumieć, bo masa istniejących projektów nadal go używa, ale nowe rzeczy poznawaj już przede wszystkim w modelu App Router.

Werdykt Labu

App Router to nie tylko nowy sposób definiowania tras, ale fundamentalna zmiana w architekturze aplikacji Next.js: Server Components domyślnie zamiast Client Components, natywne layouty zachowujące stan, wbudowane stany ładowania i błędów, streaming HTML z Suspense oraz Metadata API w miejsce next/head.

Praktyczny wniosek jest dwustronny. Dla nowego projektu wybieraj App Router — to aktywnie rozwijana ścieżka, bogatszy model renderowania i kierunek całego frameworka. Istniejący projekt na Pages Router zostaw w spokoju, dopóki działa — router jest wspierany i nie zniknie, a migruj dopiero wtedy, gdy realnie uprości architekturę albo odblokuje potrzebne funkcje, nie „bo nowsze". Jeśli planujesz migrację albo zaczynasz nowy projekt i chcesz uniknąć typowych pułapek granicy server/client, pomogę wybrać właściwe podejście i je wdrożyć — zobacz też, jak prowadzę projekty w Next.js.

  • Szybkie porównanie1 min
  • Czym się różnią?1 min
  • Kluczowe różnice2 min
  • Porównanie wydajności1 min
  • Gdzie App Router nadal potrafi boleć1 min
  • Kiedy wybrać Pages Router?1 min
  • Kiedy wybrać App Router?1 min
  • Pytanie brzmi - czy można używać obu?1 min
  • Migracja z Pages Router do App Router1 min
  • Moja rekomendacja1 min
  • Werdykt Labu1 min

Często zadawane pytania

ŹródłaZweryfikowano: 31 maja 2026

Oficjalna dokumentacja Next.js dotycząca obu routerów zweryfikowana podczas redakcji artykułu.

  • Next.js — App Router
  • Next.js — Pages Router
  • Next.js — Server Components
  • Next.js — Migrating from Pages to App Router
Maciej Sala

O autorze

Maciej Sala

Maciej Sala — project manager i frontendowiec z doświadczeniem w marketingu internetowym. Na co dzień pracuję z Reactem, Next.js i TypeScriptem, łącząc perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat związany z branżą gier wideo jako project manager i game designer.

Absolwent historii na Uniwersytecie Jagiellońskim i studiów podyplomowych z marketingu internetowego na Akademii Górniczo-Hutniczej w Krakowie. Poza pracą trenuje na siłowni, maluje figurki i realizuje własne projekty.

Moje artykułyWięcej o mnie

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy

Czytaj dalej

Zobacz więcej wpisów
Astro.js vs Next.js w 2026 — kompleksowe porównanie frameworków
Astro.js vs Next.js w 2026 — kompleksowe porównanie frameworków

Porównanie Astro 6 i Next.js 16 z perspektywy wdrożeń: architektura, JavaScript po stronie klienta, SEO, DX, hosting i konkretne przypadki użycia.

Maciej Sala

Maciej Sala

Founder Strivelab

15 kwietnia 2026
E2E testy w Next.js App Router – kompletny setup Cypress + CI/CD
E2E testy w Next.js App Router – kompletny setup Cypress + CI/CD

Cypress E2E w Next.js App Router krok po kroku. Konfiguracja, fixtures, custom commands, CI i wzorce, które ograniczają flaky testy.

Maciej Sala

Maciej Sala

Founder Strivelab

31 października 2025
Prognozy i trendy 2026: AI, GEO i React Server Components
Prognozy i trendy 2026: AI, GEO i React Server Components

Siedem trendów, które w 2026 realnie zmieniają web development i marketing: GEO, zero-click search, server-first Next.js, AI-assisted development i agentic commerce.

Maciej Sala

Maciej Sala

Founder Strivelab

8 stycznia 2026
Poprzedni wpisGit w praktyce: 10 komend, które uratują Ci życiePraktyczny przewodnik po komendach Git do ratowania zmian: stash, cherry-pick, reflog, reset, revert, bisect, rebase, diff, clean i worktree.
Maciej Sala

Maciej Sala

Founder Strivelab

18 grudnia 2025
Następny wpisLanding page dla Google Ads w Next.js — jak budować strony, które konwertująJak zaprojektować landing page w Next.js pod Google Ads: szybkość, message match, formularz, atrybucja, consent i techniczne elementy, które wpływają na wynik kampanii.
Maciej Sala

Maciej Sala

Founder Strivelab

31 grudnia 2025