Як працює серверна рендеринг (SSR) у Next.js
SSR (Рендеринг на стороні сервера) — це стратегія, при якій HTML генерується на сервері за кожним запитом користувача. На відміну від SSG, сторінка не створюється заздалегідь, а формується в реальному часі.
Як це працює
Користувач робить запит
Браузер надсилає запит на сервер. Наприклад, користувач відкриває свою профільну сторінку на IT Lead.
Сервер рендерить сторінку
Next.js запускає серверний компонент: отримує доступ до бази даних, перевіряє авторизацію, збирає дані та генерує HTML.
HTML надсилається клієнту
Користувач отримує готовий HTML з актуальними даними. Потім React гідратує сторінку на клієнті, роблячи її інтерактивною.
SSR в App Router
У App Router SSR активується, коли компонент використовує динамічні дані. Просто додайте cache: 'no-store' до виклику fetch або використовуйте динамічні функції (cookies(), headers()):
// app/profile/page.tsx
import { cookies } from 'next/headers'
import { db } from '@/lib/db'
export default async function ProfilePage() {
const session = cookies().get('session')
if (!session) return <LoginPrompt />
const user = await db.user.findUnique({
where: { sessionId: session.value }
})
return (
<div>
<h1>Привіт, {user.name}!</h1>
<p>Вирішені проблеми: {user.solvedProblems.length}</p>
</div>
)
}Використання cookies() автоматично робить цю сторінку динамічною (SSR). Next.js розуміє, що результат залежить від запиту і не може бути кешованим.
Явне динамічне рендеринг
Ви можете явно вимкнути кешування для запитів fetch:
// app/feed/page.tsx
export default async function FeedPage() {
const res = await fetch('https://api.itlead.org/feed', {
cache: 'no-store'
})
const posts = await res.json()
return <FeedList posts={posts} />
}Або встановити режим для цілого сегмента маршруту:
// app/dashboard/layout.tsx
export const dynamic = 'force-dynamic'
export default function DashboardLayout({
children
}: {
children: React.ReactNode
}) {
return <div className="dashboard">{children}</div>
}SSR в Pages Router (Спадщина)
У Pages Router SSR використовує getServerSideProps:
// pages/profile.tsx
export async function getServerSideProps(context) {
const { req } = context
const session = req.cookies.session
if (!session) {
return { redirect: { destination: '/auth/login', permanent: false } }
}
const user = await db.user.findUnique({
where: { sessionId: session }
})
return { props: { user } }
}
export default function ProfilePage({ user }) {
return (
<div>
<h1>Привіт, {user.name}!</h1>
<p>Вирішені проблеми: {user.solvedProblems.length}</p>
</div>
)
}Коли використовувати SSR
Добре для:
- Персоналізовані сторінки (профіль, налаштування, інформаційна панель)
- Контент, що залежить від cookie або заголовків (авторизація, A/B тести)
- Дані, які повинні бути актуальними на момент запиту
- Сторінки з часто змінюваним контентом, де ISR недостатньо
Не підходить для:
- Статичного контенту (документація, блог). SSG буде швидшим і дешевшим.
- Сторінок, де трохи застарілі дані є прийнятними. ISR буде більш ефективним.
SSR проти SSG
| SSG | SSR | |
|---|---|---|
| Коли генерується | Під час збірки | За кожним запитом |
| Швидкість відповіді | Миттєва (CDN) | Залежить від сервера |
| Актуальність даних | Під час збірки | Завжди актуальні |
| Навантаження на сервер | Немає | За кожним запитом |
| Персоналізація | Ні | Так |
Важливо:
SSR збільшує час до першого байта (TTFB), оскільки сервер витрачає час на рендеринг перед відправкою відповіді. Якщо сторінка виконує важкі запити до бази даних, користувач буде чекати. Використовуйте SSR свідомо, а не за замовчуванням.
Стрімінг
У App Router Next.js підтримує стрімінг HTML. Це дозволяє вам надсилати частини сторінки, як тільки вони стають готовими, не чекаючи завершення всіх запитів:
// app/dashboard/page.tsx
import { Suspense } from 'react'
export default function DashboardPage() {
return (
<div>
<h1>Інформаційна панель</h1>
<Suspense fallback={<p>Завантаження статистики...</p>}>
<UserStats />
</Suspense>
<Suspense fallback={<p>Завантаження активності...</p>}>
<RecentActivity />
</Suspense>
</div>
)
}Користувач бачить заголовок і резервні елементи відразу, поки дані завантажуються поступово. Це значно покращує сприйняту швидкість.
Корисні ресурси
- nextjs.org/docs — динамічне рендеринг
- Стрімінг та Suspense — стрімінг рендеринг
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.