Next.js 15 — co nowego i czy warto migrować z 14?

Opublikowano
10 kwietnia 2026
Aktualizacja
25 maja 2026
Czas czytania
7 min czytania

Co właściwie przynosi Next.js 15 i dlaczego to taki ważny krok?

to wielkie wydanie frameworka od Vercel, które zacieśnia współpracę z

Jeśli wciąż rozwijasz projekt na Next.js 14 — lub właśnie siadasz do pisania nowego kodu — ten artykuł pomoże Ci ocenić, co tak naprawdę zyskujesz, co musisz zmienić i na co uważać podczas migracji.

Co ciekawego kryje się pod maską Next.js 15?

React 19 staje się obowiązkowym partnerem

Next.js 15 twardo wymaga Reacta 19 i nie jest to tylko kosmetyczny wymóg. Ta wersja biblioteki przynosi mechanizmy, które wprost wpływają na to, jak projektujemy nasze aplikacje.

Oto co najbardziej ucieszy Cię w nowym React 19 z punktu widzenia pracy w Next.js:

  • React Compiler — magiczna optymalizacja i memoizacja. Zapomnij o męczeniu się z ręcznym dopisywaniem useMemo, useCallback czy React.memo w każdej możliwej sytuacji.
  • Hook use() — pozwala na natywne rozpakowywanie Promisów i czytanie kontekstów prosto z renderu.
  • Actions — spójny, jednolity model obsługi formularzy i mutacji danych, niezależnie od tego, czy działasz po stronie klienta, czy serwera.
  • Usprawnione Suspense — znacznie lepsza obsługa strumieniowania danych (streamingu) i stanów ładowania (fallbacków).
Code
// React 19 — wykorzystanie nowego hooka use() w Server Component
import { use } from 'react'
 
async function getProduct(id: string) {
  const res = await fetch(`https://api.example.com/products/${id}`)
  return res.json()
}
 
export default function ProductPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = use(params)
  const product = use(getProduct(id))
 
  return (
    <article>
      <h1>{product.name}</h1>
      <p>{product.description}</p>
      <span>{product.price} PLN</span>
    </article>
  )
}

Turbopack — błyskawiczna praca deweloperska

Turbopack, nowy bundler napisany w wydajnym języku Rust, w wersji 15 osiągnął wreszcie status stabilny dla trybu deweloperskiego (next dev). Pamiętaj jednak, że nie jest odpalany domyślnie. By z niego skorzystać, musisz dopisać flagę --turbopack (dotyczy to wersji Next.js 15.0–15.4.x). Gwarantuję, że w porównaniu ze starym Webpackiem poczujesz ogromną różnicę od pierwszego kliknięcia.

Co mierzymyWebpackTurbopack
Uruchomienie na zimno (next dev)3–8 s0.5–2 s
Przeładowanie modułu (HMR)200–800 ms20–80 ms
"Zjadanie" pamięci RAMZnaczneUtrzymane w ryzach

Jedna uwaga: tworzenie paczki produkcyjnej (next build) przy użyciu Turbopacka w Next.js 15 nadal tkwi w fazie eksperymentalnej i domyślnie framework skorzysta ze sprawdzonego Webpacka. Turbopack stał się całkowicie domyślny (zarówno dla dev jak i build) dopiero od wersji Next.js 16.

Code
# Tak odpalisz Turbopacka podczas developmentu (Next.js 15)
next dev --turbopack
 
# A tak uruchomisz standardowy silnik Webpack (domyślnie bez flagi)
next dev

W Next.js 16 role się odwracają: Turbopack to król domyślności, a Webpack staje się specjalnym wyborem aktywowanym przez flagę --webpack.

Wywrócenie cache'u do góry nogami — domyślnie "bez zapamiętywania"

To prawdopodobnie najbardziej uciążliwa dla starych projektów (tzw. breaking change) modyfikacja w Next.js 15, ale zarazem ta, za którą masa programistów jest najbardziej wdzięczna.

W Next.js 14 każde żądanie fetch() w Server Components było przez system "magicznie" buforowane (zachowanie force-cache). Wielu z nas godzinami rwało włosy z głowy, zastanawiając się, dlaczego zaktualizowane dane nie chcą pojawić się na stronie bez sztucznego wymuszania rewalidacji.

Wersja 15 brutalnie ucina tę magię, ustawiając domyślny zachowanie na no-store — co oznacza, że żadne żądanie fetch nie zostanie zapamiętane, o ile sam mu tego nie rozkażesz.

Code
// Era Next.js 14 — tu działała magia domyślnego buforowania (force-cache)
const data = await fetch('https://api.example.com/data')
 
// Era Next.js 15 — domyślnie NIE zapamiętujemy danych (no-store)
const data = await fetch('https://api.example.com/data')
 
// Jeśli jednak chcesz starego zachowania w Next.js 15, robisz to jawnie:
const data = await fetch('https://api.example.com/data', {
  cache: 'force-cache',
})
 
// Możesz też ustawić rewalidację opartą o czas (w sekundach)
const data = await fetch('https://api.example.com/data', {
  next: { revalidate: 3600 },
})

Nowy drogowskaz: dyrektywa "use cache"

W samej "piętnastce" użycie dyrektywy "use cache" to wciąż faza eksperymentalna, która z początku nie miała stanowić szybkiego zamiennika dla funkcji unstable_cache. Był to raczej wyraźny drogowskaz na to, jak w przyszłości będziemy podchodzić do buforowania na poziomie całych funkcji i komponentów (co ostatecznie bardzo mocno ewoluowało w nowszych wersjach pod szyldem Cache Components).

Code
// Zapamiętanie wyniku dla całej asynchronicznej funkcji
async function getProducts() {
  'use cache'
  const res = await fetch('https://api.example.com/products')
  return res.json()
}
 
// Możemy też buforować dane z tagiem ułatwiającym późniejsze odświeżanie
import { cacheTag } from 'next/cache'
 
async function getProduct(id: string) {
  'use cache'
  cacheTag(`product-${id}`)
  const res = await fetch(`https://api.example.com/products/${id}`)
  return res.json()
}

Partial Prerendering (PPR) — fascynujący eksperyment

Partial Prerendering to fantastyczne połączenie dwóch światów: szybkiego statycznego wczytywania i elastycznej dynamiki generowanej w locie, w ramach jednej i tej samej podstrony. To znaczy, że użytkownik niemal natychmiast dostaje bazowy "szkielet" z najbliższego -a, podczas gdy brakujące informacje dynamiczne doczytują (streamują) się sobie w tle.

Code
// plik next.config.ts
const nextConfig = {
  experimental: {
    ppr: 'incremental',
  },
}
 
export default nextConfig

Z perspektywy historycznej: w Next.js 15 musieliśmy wywoływać to ręcznie przez experimental.ppr. Dziś ten sam nurt technologiczny żyje sobie własnym życiem pod postacią Cache Components i jest ściśle połączony z użyciem komponentu Suspense.

Code
// app/product/[id]/page.tsx
import { Suspense } from 'react'
 
// Sztywny, statyczny szkielet generowany podczas budowy projektu
export default async function ProductPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
 
  return (
    <main>
      <h1>Produkt #{id}</h1>
      <StaticProductInfo id={id} />
 
      {/* Spersonalizowana sekcja z dynamicznymi danymi — tu wjeżdża streaming */}
      <Suspense fallback={<PriceSkeleton />}>
        <DynamicPrice id={id} />
      </Suspense>
 
      <Suspense fallback={<ReviewsSkeleton />}>
        <DynamicReviews id={id} />
      </Suspense>
    </main>
  )
}

Co jeszcze warto mieć na radarze?

  • next/after — nowiutkie, w pełni stabilne . Idealne do odpalania cięższego kodu (logów, telemetrii, porządków) bez opóźniania odpowiedzi dla użytkownika.
  • instrumentation.ts — nareszcie stabilny hak ułatwiający zapięcie narzędzi monitorujących jak Sentry czy OpenTelemetry.
  • <Form> — własny komponent Next.js, ułatwiający tworzenie płynnych, inteligentnych formularzy z domyślnym mechanizmem progressive enhancement i wstępnym doczytywaniem.
  • Wskaźnik stron statycznych — super ułatwienie dla deweloperów. Aplikacja pokaże Ci ikonkę zdradzającą, które trasy udało się poprawnie i statycznie wygenerować.

Czy to już czas na pożegnanie z Next.js 14?

Zabieraj się za migrację, jeśli:

  • Czas to dla Ciebie pieniądz — wejście na Turbopacka w środowisku dev uchroni Cię od długiego czekania na przeładowania.
  • Masz dość walki z systemem cache Next.js 14 — nowe zasady gry, stawiające no-store jako opcję domyślną, usuną potężną kulę u Twojej nogi.
  • Czekasz na ficzery Reacta 19 — nowy zestaw hooków oraz obietnica React Compilera wymagają oparcia projektu o środowisko piętnastki.
  • Działasz hybrydowo — architektury stron mieszające statykę i personalizowane, doczytywane zjawiska, wręcz domagają się eksperymentów z mechanizmami pokroju PPR.

Bądź wstrzemięźliwy, jeśli:

  • Siedzisz głęboko w ustawieniach Webpacka — zanim przesiądziesz się na Turbopack, dwa razy sprawdź, czy Twoje niestandardowe wtyczki uciągną tę rewolucję.
  • Twoje kluczowe biblioteki wciąż żyją w erze Reacta 18 — rzuć okiem na pule zależności i daj twórcom czas na wydanie łatek.
  • Projekt na produkcji pędzi jak dobrze naoliwiona maszyna — przesiadka między takimi "majorowymi" wersjami na czystym organizmie biznesowym zawsze niesie w sobie nutę nieprzewidywalnego ryzyka.

Jak bezboleśnie przepiąć projekt na nową wersję? (krok po kroku)

1. Zaktualizuj kluczowe środowisko

Code
npm install next@15 react@19 react-dom@19

2. Zaprzęgnij Codemod do brudnej roboty

Załoga z Vercel dostarcza narzędzie, które z automatu zrobi dla Ciebie gruntowne porządki. Odpal polecenie:

Code
npx @next/codemod@latest upgrade latest

Zauważ jednak, że Codemod ogarnie za Ciebie składnię importów czy przestarzałe nazewnictwo, ale nie zaingeruje w Twoją logikę biznesową, jeśli np. wymagała ona sztywnego modelu starego cache'a.

3. Zrób porządny audyt operacji fetch()

Bez tego kroku daleko nie ujedziesz. Przejedź po każdym starym poleceniu fetch() w obrębie Server Components i świadomie zadeklaruj, które zapytania mają "trzymać" pamięć:

Code
// Sztywne dane – jak drzewo kategorii. Dodajemy jawnie zapamiętywanie:
const categories = await fetch('https://api.example.com/categories', {
  cache: 'force-cache',
})
 
// Dynamiczne i wrażliwe struktury, np. stany koszyka czy strefy logowania – zostawiamy bez dopisków (bo Next 15 domyślnie je przeładuje):
const cart = await fetch('https://api.example.com/cart')

4. Przejrzyj swoje asynchroniczne parametry

W świecie Next.js 15 struktury params oraz searchParams w layoutach i na poziomie podstron wchodzą w pełną asynchroniczność. Twój kod musi nadążać za tymi zasadami:

Code
// Stara szkoła Next.js 14
export default function Page({ params }: { params: { id: string } }) {
  const id = params.id
}
 
// Nowa szkoła Next.js 15
export default async function Page({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
}

5. Męcz aplikację, aż nabierzesz pewności

Puść całą serię testów automatycznych, przeklikaj środowisko deweloperskie i zrób deployment na bezpieczny tzw. preview. Wdróż to na produkcję dopiero gdy wyłapiesz i zneutralizujesz wszystkie niedociągnięcia z bibliotekami.

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

Często zadawane pytania

Co najważniejszego zmienia Next.js 15 względem 14?

Cztery rzeczy: (1) fetch() w Server Components nie jest już cachowany domyślnie — od teraz no-store, (2) params i searchParams są asynchroniczne (await params), (3) Turbopack jest stabilny w next dev (włączasz go flagą --turbopack) i drastycznie przyspiesza HMR (20–80 ms vs 200–800 ms w Webpacku), (4) wymagany jest React 19 z React Compiler, use() hookiem i Actions.

Tak. Next.js 15 jest wersją stabilną i działa na produkcji od końca 2024 r. Jednocześnie część nowości opisywanych w kontekście renderingu i cachowania (PPR, wczesne "use cache") miała w tej wersji status eksperymentalny i dopiero w kolejnych wydaniach (Next.js 16+) dojrzała do obecnego modelu Cache Components.

Tak — Next.js 15 wymaga React 19 jako minimalnej wersji. Nie da się używać Next.js 15 z React 18. Przed migracją zweryfikuj, czy biblioteki trzecie (UI kity, formularze, animacje) są kompatybilne z React 19 — to największe ryzyko migracji.

W Next.js 15 — nie w pełni. Turbopack jest stabilny w next dev, ale wymaga jawnej flagi --turbopack (nie jest domyślny). W next build Webpack pozostaje domyślny, a wsparcie produkcyjne Turbopacka jest w fazie alpha/beta. W Next.js 16 Turbopack stał się domyślny dla next dev i next build, a Webpack jest opt-in przez --webpack.

Dla małych projektów (do 30 stron) — kilka godzin. Dla średnich aplikacji — 1–2 dni. Dla dużych aplikacji z rozbudowanym cachem, niestandardową konfiguracją Webpacka i bibliotekami trzecimi niezgodnymi z React 19 — 3–7 dni testowania i audytu. Codemod (npx @next/codemod@latest upgrade latest) automatyzuje 70–80% zmian.

Audyt jest obowiązkowy. W Next.js 14 fetch() był domyślnie cachowany — w 15 nie jest. Po migracji niektóre dane, które „magicznie" działały, przestaną. Przejdź każde wywołanie fetch() w Server Components i jawnie zdecyduj: dane statyczne (kategorie, treści CMS) → cache: 'force-cache' lub next: { revalidate: 3600 }, dane dynamiczne (koszyk, sesja, ceny) → bez zmiany (nowy default no-store).

Tak. Server Actions są stabilne od Next.js 14 i w 15 zyskały dodatkowe usprawnienia — lepszą integrację z React 19 Actions (useActionState, useFormStatus, useOptimistic), poprawne typy dla formData i obsługę progressive enhancement out-of-the-box. To rekomendowane podejście do mutacji danych w App Routerze.

O autorze

Maciej Sala

Maciej Sala — Product Manager i Frontend Developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty side-projecty.

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