SSR: Server Side Rendering
Server Side Rendering (SSR) — стратегия рендеринга, при которой сервер генерирует полный HTML-документ при каждом запросе и отправляет его браузеру; клиент затем «оживляет» страницу через процесс hydration.
Зачем нужно
Чистый CSR отдаёт браузеру пустой HTML — поисковые роботы и пользователи видят контент только после загрузки и выполнения JS. SSR решает эту проблему: первый байт HTML уже содержит готовый контент, FCP (First Contentful Paint) быстрый, SEO работает нативно. После загрузки JS происходит hydration — React «привязывается» к серверному HTML и дальше приложение работает как SPA.
Где используется
- E-commerce (страницы товаров с SEO, актуальными ценами и остатками)
- Новостные сайты и медиа-платформы
- Приложения с персонализированным контентом на основе сессии пользователя
- Любые публичные страницы, где важны SEO и быстрый FCP
Как работает SSR
Запрос GET /product/42
↓
Next.js сервер
↓
getServerSideProps: загружает данные о товаре (БД/API)
↓
React рендерит компонент в HTML-строку (renderToString)
↓
Сервер отправляет полный HTML + данные (JSON) в `__NEXT_DATA__`
↓
Браузер: мгновенно показывает HTML (быстрый FCP)
↓
Браузер загружает bundle.js
↓
Hydration: React читает `__NEXT_DATA__`, привязывается к DOM
↓
Страница интерактивна (TTI)
Next.js Pages Router: getServerSideProps
// pages/product/[id].jsx
// Вызывается при КАЖДОМ запросе на сервере
export async function getServerSideProps(context) {
const { params, req, res } = context;
// Доступ к cookies для персонализации
const userId = req.cookies['user-id'];
// Загрузка данных при каждом запросе
const [product, recommendations] = await Promise.all([
fetchProduct(params.id),
fetchRecommendations(params.id, userId),
]);
if (!product) {
return { notFound: true };
}
// Кэширование на уровне HTTP
res.setHeader('Cache-Control', 'public, s-maxage=10, stale-while-revalidate=59');
return {
props: {
product,
recommendations,
},
};
}
export default function ProductPage({ product, recommendations }) {
return (
<main>
<h1>{product.name}</h1>
<p>{product.price} ₽</p>
<RecommendationsList items={recommendations} />
</main>
);
}
Next.js App Router: Server Components (новый SSR)
// app/product/[id]/page.tsx
// В App Router SSR — это просто async Server Component
async function ProductPage({ params }: { params: { id: string } }) {
const product = await fetch(`https://api/products/${params.id}`, {
// no-store = всегда свежие данные (SSR-поведение)
cache: 'no-store',
}).then(r => r.json());
return (
<main>
<h1>{product.name}</h1>
<p>{product.price} ₽</p>
</main>
);
}
Hydration mismatch — частая проблема
// Эта ошибка возникает когда сервер и клиент рендерят разное
function RandomComponent() {
// Math.random на сервере даёт одно значение,
// на клиенте при hydration — другое → mismatch error
const id = Math.random; // НЕ ДЕЛАЙТЕ ТАК
// Правильно: используйте useId или фиксированное значение
const id = React.useId;
return <div id={id}>...</div>;
}
Частые ошибки
- Hydration mismatch — HTML от сервера отличается от того, что React генерирует на клиенте; типичные причины:
Math.random,Date.now(), браузерные API в рендере. - Слишком много данных в SSR — загружают всю страницу через SSR, хотя только шапка нужна серверу; остальное лучше загружать на клиенте.
- Нет кэширования HTTP-заголовков — каждый запрос к SSR-странице создаёт нагрузку на сервер; настраивайте
Cache-Controlдля частично-кэшируемого контента.
Связанные темы
- _MOC SPA
- CSR, SSR, SSG -- обзор подходов
- SSG -- Static Site Generation
- ISR -- Incremental Static Regeneration
- Next.js -- обзор
- React Server Components