Пошук уроків, статей та іншого контенту
Три абревіатури, що описують, коли й де рендериться сторінка — і чому в App Router вони працюють інакше, ніж в старому Pages Router.
SSR, SSG та ISR з'явились ще в Pages Router Next.js (getServerSideProps, getStaticProps, revalidate) як три явно окремі функції-експорти, які розробник обирав вручну. App Router (з якого зроблений цей курс — стаття написана для Next.js 16) не має цих функцій: замість них рендеринг визначається тим, як компонент отримує дані, а самі терміни лишаються зручним способом говорити про те, коли саме генерується HTML.
HTML генерується один раз, під час збірки (build), і надалі віддається як готовий статичний файл — найшвидший варіант для користувача, бо сервер взагалі не виконує жодного коду на кожен запит. У App Router для цього використовують generateStaticParams (щоб Next.js знав заздалегідь, які саме сторінки з динамічними сегментами шляху існують) разом із кешованим fetch:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await getAllPostSlugs();
return posts.map((slug) => ({ slug }));
}
async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await fetch(`https://api.example.com/posts/${slug}`, {
cache: "force-cache", // явно кешувати — обов'язково в Next.js 15+
}).then((r) => r.json());
return <article>{post.title}</article>;
}Важлива відмінність від старіших версій Next.js: починаючи з Next.js 15, fetch() більше не кешується за замовчуванням (стаття «Стратегії рендерингу: SSR, SSG та ISR» курсу Next.js розбирає це докладніше). Щоб отримати статичну генерацію, потрібно явно вказати cache: "force-cache" — без цього маршрут поводитиметься як динамічний (SSR), навіть якщо технічно міг би бути статичним.
HTML генерується на сервері на кожен окремий запит, у реальному часі. Це відбувається автоматично, щойно маршрут звертається до чогось, що не може бути відоме заздалегідь під час збірки: cookies(), headers(), searchParams (без generateStaticParams) або fetch без явного кешування. SSR гарантує максимально свіжі дані ціною того, що сервер виконує роботу на кожен запит.
Компроміс між SSG і SSR: сторінка генерується статично (як у SSG), але Next.js періодично перегенеровує її у фоні, не блокуючи користувачів застарілою версією на час перегенерації. Задається через revalidate:
// app/blog/[slug]/page.tsx
export const revalidate = 3600; // перегенерувати не частіше ніж раз на годину
async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await getPost(slug);
return <article>{post.title}</article>;
}Перший запит після спливання години все ще отримує стару (можливо, злегка застарілу) версію сторінки миттєво, а Next.js перегенеровує її у фоні для наступних відвідувачів — на відміну від чистого SSR, користувач ніколи не чекає на повну генерацію сторінки в реальному часі.
SSG — генерується один раз під час збірки, найшвидше для користувача, підходить для контенту, що майже не змінюється (документація, маркетингові сторінки).
SSR — генерується на кожен запит, завжди свіжі дані, повільніше за SSG, підходить для персоналізованого чи часто змінюваного контенту (дашборд користувача, кошик).
ISR — статична генерація з періодичним фоновим оновленням, компроміс швидкості SSG і свіжості SSR, підходить для контенту, що змінюється, але не критично часто (каталог товарів, блог).
Очікувати статичну генерацію «за замовчуванням», як це було в старіших версіях Next.js, — у Next.js 15+ маршрут із fetch без явного cache: "force-cache" стає динамічним автоматично.
Ставити занадто малий revalidate «про всяк випадок» — це фактично перетворює ISR на SSR (перегенерація на кожен чи майже кожен запит), втрачаючи головну перевагу підходу.
Плутати ISR із real-time оновленням — між закінченням revalidate-періоду і фактичною фоновою перегенерацією користувачі можуть недовго бачити застарілі дані; для справді миттєвих оновлень (наприклад, після дії адміністратора) варто явно викликати on-demand revalidation (revalidatePath/revalidateTag) замість того, щоб покладатись лише на таймер.
У App Router Next.js SSR/SSG/ISR — це вже не окремі API, а результат того, як саме маршрут отримує дані: явно закешований fetch дає статичну генерацію (SSG), звернення до динамічних даних без кешу дає рендеринг на кожен запит (SSR), а revalidate поєднує обидва підходи через періодичну фонову перегенерацію (ISR). Найважливіша практична деталь для Next.js 15+ — кешування тепер потрібно вмикати явно, а не вимикати.