Next.js

Baza pytań rekrutacyjnych i wiedzy. Filtruj, szukaj i sprawdzaj swoją wiedzę.

Tematy
mediumnextjsrenderingssr+1

Odpowiedź

SSR generuje HTML przy każdym żądaniu, więc może używać danych per‑request (np. autoryzacja, nagłówki), ale obciąża serwer. SSG tworzy strony w czasie builda i serwuje je jako pliki statyczne, co daje dużą szybkość i cache’owalność, ale świeżość danych zależy od builda lub ISR.

mediumapp-routerserver-componentsclient-components+1

Odpowiedź

Server Components renderują się na serwerze, mogą bezpośrednio korzystać z backendu i nie są wysyłane do przeglądarki; nie mogą używać hooków klienta. Client Components są oznaczone 'use client', działają w przeglądarce, wspierają hooki/stan i interakcje, ale zwiększają bundle JS.

Odpowiedź

W App Routerze każdy folder jest segmentem trasy odpowiadającym części URL. Plik layout.tsx w segmencie opakowuje wszystkie strony i layouty poniżej; layouty zagnieżdżone składają się i mogą utrzymywać stan między nawigacjami, co pozwala na wspólne UI jak navbar czy sidebar.

Odpowiedź

ISR pozwala serwować stronę statyczną, ale okresowo rewalidować ją w tle. Użytkownicy dostają szybko cache’owaną wersję, a gdy się zestarzeje, Next.js generuje nową bez pełnego redeployu. Stosuj dla stron głównie statycznych z rzadkimi zmianami.

Odpowiedź

Next.js domyślnie cache’uje fetch’e na serwerze w zależności od ustawień żądania i trasy. Możesz to wyłączyć przez cache: 'no-store' lub ustawić czas rewalidacji, aby odświeżać dane okresowo. revalidatePath/revalidateTag pozwalają unieważniać cache stron lub danych na żądanie.

export const revalidate = 60

const res = await fetch('https://api.example.com/posts', { next: { revalidate: 60 } })
const posts = await res.json()

Odpowiedź

Server Components renderują się na serwerze, mogą bezpośrednio używać backendu i nie wspierają hooków/eventów. Client Components działają w przeglądarce, mogą używać `useState/useEffect` i handlerów, ale dokładają JS do bundla.

easyuse-clientclient-componentreact

Odpowiedź

Oznacza plik jako granicę Client Component. Komponent (i jego zależności) trafia do bundla przeglądarki, więc możesz używać hooków i event handlerów.

Odpowiedź

Tworzysz folder np. `app/posts/[id]/page.tsx`. W Server Component czytasz z props `params`, a w Client Component możesz użyć `useParams()`.

export default function Page({ params }: { params: { id: string } }) {
  return <div>Post id: {params.id}</div>
}

Odpowiedź

SSR renderuje przy każdym żądaniu, SSG renderuje na etapie builda, a ISR odświeża stronę w tle po czasie revalidate. To kompromis między świeżością danych, szybkością i czasem builda.

Odpowiedź

W Server Components Next może cachować wyniki `fetch()` i deduplikować requesty. Możesz to wyłączyć przez `cache: 'no-store'` albo ustawić revalidate przez `next: { revalidate: sekundy }`, żeby kontrolować świeżość.

const res = await fetch('https://example.com/api', {
  next: { revalidate: 60 },
})

Odpowiedź

Middleware działa przed obsługą route (często na edge) i może robić redirect/rewrite (np. locale routing, bramki auth). Powinno być lekkie i ma ograniczenia runtime względem pełnego Node.js (nie wszystkie API są dostępne).

Odpowiedź

Dzieje się, gdy HTML z SSR różni się od pierwszego renderu w przeglądarce (np. `Math.random()`, `Date.now()`, warunki na `window`, formatowanie locale). Naprawiasz przez deterministyczny pierwszy render albo przeniesienie wartości client-only do `useEffect`/Client Components.

Odpowiedź

Streaming pozwala serwerowi wysyłać HTML „kawałkami” w miarę dostępności danych. Granice `Suspense` (i `loading.tsx`) pokazują fallback, gdy segment się ładuje, co poprawia odczuwalną wydajność i TTFB.

Odpowiedź

Server Actions to funkcje uruchamiane na serwerze, które można wywołać z formularzy lub Client Components. Traktuj je jak publiczne endpointy: waliduj input i wymuszaj auth/autoryzację na serwerze (nie ufaj UI).

Odpowiedź

Trzymaj jak najwięcej w Server Components (mniej JS), a ciężki kod clientowy dziel przez dynamic importy. Dodatkowo używaj `next/image` do optymalizacji obrazów i unikaj ogromnych providerów po stronie klienta.

Odpowiedź

`Link` umożliwia nawigację po stronie klienta (bez pełnego przeładowania) i może prefetchować trasy, co przyspiesza przejścia i zachowuje stan aplikacji. `<a>` używaj głównie do linków zewnętrznych.

mediumapp-routeruseRouternavigation

Odpowiedź

W Client Component użyj `useRouter()` z `next/navigation` i wywołaj `router.push()` / `router.replace()`. W Server Components zwykle robisz redirect przez `redirect()`.

'use client'

import { useRouter } from 'next/navigation'

export function GoButton() {
  const router = useRouter()
  return (
    <button onClick={() => router.push('/en')}>Go</button>
  )
}

Odpowiedź

`useParams()` czyta parametry dynamicznych tras (np. `[id]`), a `useSearchParams()` czyta query string. Oba to hooki klientowe, więc można ich używać tylko w Client Components.

Odpowiedź

Edge runtime działa bliżej użytkownika i może zmniejszyć opóźnienie dla lekkiej logiki (redirecty, proste auth). Node.js runtime jest bardziej elastyczny (pełne API Node, cięższe zależności) i lepszy do złożonych zadań serwerowych, np. sterowników DB i ciężkich obliczeń.

harddata-fetchingpromise-allsuspense+1

Odpowiedź

Uruchamiaj niezależne requesty równolegle (np. `Promise.all`), zamiast czekać po kolei, i używaj granic `Suspense`, żeby streamować UI w miarę dostępności danych. To poprawia całkowitą latencję i odczuwalną szybkość.

easycode-splittingdynamic-importperformance

Odpowiedź

Code splitting ładuje kod tylko wtedy, gdy jest potrzebny, zamiast wysyłać jeden wielki bundle. `next/dynamic` pozwala leniwie doładować ciężkie komponenty (i opcjonalnie wyłączyć SSR), poprawiając start aplikacji.

Odpowiedź

Użyj `cookies()` i `headers()` z `next/headers` w Server Component. Czytają one dane z requestu po stronie serwera; w przeglądarce cookies czyta się inaczej (a headerów nie masz w ten sam sposób).

import { cookies, headers } from 'next/headers'

export default function Page() {
  const cookieStore = cookies()
  const theme = cookieStore.get('theme')?.value
  const ua = headers().get('user-agent')
  return <div>{theme} {ua}</div>
}

Odpowiedź

Route Handler to endpoint serwerowy w App Router (np. `app/api/x/route.ts`). Użyj go, gdy potrzebujesz własnego HTTP API (webhooki, upload plików, publiczne endpointy) albo gdy klient musi wołać API przez fetch.

hardserver-actionsroute-handlerssecurity+1

Odpowiedź

Server Actions są dobre do mutacji serwerowych powiązanych z UI/formami (nadal walidujesz i autoryzujesz). Route Handlers wybierz, gdy potrzebujesz ogólnego HTTP API (publiczni klienci, webhooki, third-party, własne metody/headery) albo przepływów jak upload.

Odpowiedź

Jeśli trasa zależy od danych per-request (cookies/headery/auth), musi być dynamiczna. Możesz to wymusić przez `fetch(..., { cache: 'no-store' })`, odczyt `cookies()/headers()` albo `export const dynamic = 'force-dynamic'`.

Odpowiedź

`next/image` automatycznie optymalizuje obrazy: serwuje odpowiedni rozmiar, wspiera nowoczesne formaty, domyślnie lazy-loaduje i pomaga uniknąć “skakania” layoutu, gdy podasz wymiary. To zwykle lepsze niż wysyłanie jednego ogromnego obrazka wszędzie.

Odpowiedź

`generateMetadata` pozwala tworzyć per-route metadane SEO (title/description/open graph) na podstawie parametrów lub danych z fetch. Działa po stronie serwera, więc łatwo wygenerować poprawne metadane dla tras dynamicznych (np. strona produktu) bez dublowania logiki.

Odpowiedź

Tylko zmienne z prefixem `NEXT_PUBLIC_` trafiają do bundla w przeglądarce. Zmienne bez tego prefixu są server-only. Zasada: nigdy nie wkładaj sekretów (API key, hasła do DB) do zmiennych `NEXT_PUBLIC_`.

Odpowiedź

`router.refresh()` wymusza ponowne renderowanie aktualnej trasy i ponowne pobranie danych dla Server Components (z uwzględnieniem cache). Użyj po mutacji (często po Server Action), gdy chcesz odświeżyć server-renderowany UI bez pełnego przeładowania strony.

Odpowiedź

Trzymaj sesję w cookie httpOnly i waliduj ją po stronie serwera (Server Components i Route Handlers). Middleware używaj głównie do routingu/redirectów, ale autoryzację i tak egzekwuj w kodzie serwera. Nie polegaj tylko na checkach po stronie klienta i uważaj na renderowanie statyczne, gdy treść zależy od użytkownika.

Odpowiedź

`error.tsx` to UI error boundary dla segmentu trasy (błędy w runtime) i może pokazać fallback oraz umożliwić reset. `not-found.tsx` renderuje się, gdy wywołasz `notFound()` albo trasy nie da się rozwiązać, żeby pokazać stronę typu 404 dla danego segmentu.

Odpowiedź

Route Groups pozwalają grupować trasy i współdzielić layouty bez wpływu na URL. Nazwa folderu w nawiasach nie jest częścią ścieżki routingu. To przydatne do porządkowania dużej aplikacji (np. marketing vs app) przy zachowaniu czystych URL-i.

Odpowiedź

`next/font` pomaga ładować fonty w zoptymalizowany sposób (self-hosting, automatyczny CSS, opcjonalne subsety i preload). Zmniejsza CLS, bo ładowanie fontów jest bardziej przewidywalne i unikasz późnych “podmian fontu”, które zmieniają rozmiar tekstu.

Odpowiedź

Dzieje się tak, gdy serwer renderuje jedno UI (np. ikona jasnego motywu), a klient po odczycie localStorage lub motywu systemowego renderuje inne, więc HTML się nie zgadza. Rozwiązania: spraw, żeby serwer znał motyw (cookie), albo renderuj elementy zależne od motywu dopiero po mount (client-side), albo pokaż stabilny placeholder i zaktualizuj w `useEffect` (opcjonalnie z `suppressHydrationWarning`).

Odpowiedź

Trzymaj kod przeglądarkowy w Client Component (`'use client'`). Jeśli biblioteka używa `window` już przy imporcie, wczytaj ją przez `dynamic(() => import(...), { ssr: false })`. Nie importuj takich modułów w Server Components i trzymaj granicę klienta jak najmniejszą, żeby ograniczyć JS wysyłany do przeglądarki.

easynextjsserver-componentsclient-components+1

Odpowiedź

Server Components są domyślne w App Router i działają na serwerze, więc świetnie nadają się do pobierania danych i ograniczania JS w przeglądarce. Client Components są potrzebne do stanu, efektów, event handlerów i API przeglądarki. Używaj `'use client'` tylko tam, gdzie to konieczne.

Odpowiedź

Server Actions to funkcje uruchamiane po stronie serwera, wywoływane z formularzy lub Client Components. Są wygodne do mutacji bez osobnych endpointów API. Ograniczenia: muszą być async, argumenty muszą być serializowalne i nie mają dostępu do API przeglądarki.

Odpowiedź

`loading.tsx` dostarcza UI ładowania dla segmentu trasy, pokazywane podczas streamingu lub gdy segment jest zawieszony. Działa z React Suspense i pozwala pokazać część UI wcześniej, zamiast czekać na całą stronę.

Odpowiedź

`generateStaticParams` mówi Next.js, które parametry tras dynamicznych zbudować statycznie podczas builda (SSG). Zwraca listę parametrów dla segmentu. Trasy spoza listy mogą być renderowane na żądanie, zależnie od ustawień dynamic/SSG.

Odpowiedź

`revalidatePath` unieważnia cache danych dla konkretnej ścieżki trasy, a `revalidateTag` unieważnia wszystkie cache’owane fetch’e oznaczone danym tagiem. Używa się tego po mutacjach (często w Server Actions), aby odświeżyć dane bez pełnego reloadu.

Odpowiedź

Tworzysz plik `route.ts`/`route.js` i eksportujesz metody HTTP typu `GET`, `POST`. Handlery używają webowych API `Request`/`Response`. Służą do własnych API, webhooków lub logiki backendowej bez osobnego serwera.

export async function GET() {
  return Response.json({ ok: true })
}

Odpowiedź

Middleware uruchamia się przed zakończeniem requestu (często na edge) i świetnie nadaje się do redirectów, rewrite’ów i bramkowania auth. Ograniczenia: działa w runtime edge (bez API Node.js), powinno być szybkie i nie jest miejscem na ciężki dostęp do DB.

Odpowiedź

`next/link` może prefetchować trasy widoczne w viewport, żeby nawigacja była szybsza. Możesz to wyłączyć przez `prefetch={false}`, gdy jest zbędne lub zbyt kosztowne. Prefetch zwykle dzieje się w tle i korzysta z cache.

Odpowiedź

Trasa staje się dynamiczna, gdy używa danych zależnych od requestu (cookies, headers) albo wyłącza cache (`cache: 'no-store'`). Możesz wymusić zachowanie konfiguracją segmentu, np. `dynamic = 'force-static'` lub `dynamic = 'force-dynamic'`.

Odpowiedź

`cache: 'no-store'` wyłącza cache i zawsze pobiera świeże dane. `revalidate` ustawia TTL dla cache, dając zachowanie typu ISR, gdzie dane odświeżają się po N sekundach. Oba ustawienia kontrolują cache fetchy po stronie serwera.