Что такое серверный рендеринг (SSR) и как он реализован в Next.js?

Серверный рендеринг (Server-Side Rendering, SSR) — это подход, при котором HTML-страница генерируется на сервере и отправляется клиенту уже в готовом виде. Это отличается от классического SPA (Single Page Application), где HTML создаётся на стороне клиента после загрузки JavaScript-кода. SSR позволяет ускорить первую отрисовку страницы, улучшить SEO и сделать приложение доступным даже при медленном соединении.

Как работает SSR:

  1. Пользователь отправляет HTTP-запрос (например, открывает страницу в браузере).

  2. Сервер обрабатывает запрос, собирает данные, рендерит React-компоненты в HTML-строку.

  3. Эта HTML-страница отправляется клиенту.

  4. После загрузки клиентский JavaScript "гидратирует" страницу — прикрепляет обработчики событий к уже отрендеренной разметке.

  5. Приложение становится интерактивным.

Преимущества SSR:

  • Быстрый Time to First Byte (TTFB): пользователь быстрее видит контент.

  • Улучшенная SEO: поисковые боты получают полноценный HTML с контентом, а не пустой div и JS-бандл.

  • Поддержка предварительного рендеринга: можно сгенерировать HTML на основе данных из API, cookies и т.д.

Next.js и SSR:

Next.js — фреймворк поверх React, который предоставляет встроенную поддержку SSR, наряду с другими стратегиями рендеринга (SSG, ISR, CSR). Он позволяет создавать страницы, которые рендерятся на сервере при каждом запросе с помощью специальных функций.

SSR в Next.js реализуется с помощью getServerSideProps

Это функция, которую можно экспортировать из страницы (pages/*.tsx). Она вызывается на сервере при каждом запросе и возвращает props, которые передаются компоненту страницы.

Пример:

// pages/profile.tsx
import React from 'react';
type Props = {
user: { id: number; name: string };
};
export const getServerSideProps = async () => {
const res = await fetch('https://api.example.com/user');
const user = await res.json();
return { props: { user } };
};
const ProfilePage = ({ user }: Props) => {
return (
<div>
<h1>Hello, {user.name}</h1>
</div>
);
};
export default ProfilePage;
  • getServerSideProps выполняется на Node.js-сервере.

  • Он может получать context, где есть req, res, query-параметры, cookies и т.д.

  • Используется, когда нужно всегда получать свежие данные.

Сравнение SSR с другими подходами в Next.js:

Подход Когда выполняется Пример функции Где генерируется HTML
SSR На каждый запрос getServerSideProps Сервер
--- --- --- ---
SSG (Static Gen.) Во время билда getStaticProps Сервер (на build time)
--- --- --- ---
ISR (Revalidate) По расписанию getStaticProps + revalidate Сервер
--- --- --- ---
CSR На клиенте useEffect, fetch в компоненте Браузер
--- --- --- ---

Типичный use-case SSR:

  • Страницы, зависимые от пользовательских данных, авторизации (cookie, токены).

  • Динамическое содержимое, где данные часто меняются.

  • SEO-важные страницы с персонализированным контентом.

Особенности SSR в Next.js:

1. Доступ к req и res:

В getServerSideProps доступен context.req и context.res. Это позволяет:

  • читать куки, заголовки,

  • перенаправлять (redirect),

  • делать условную отрисовку.

Пример с редиректом:

export const getServerSideProps = async (context) => {
const { req } = context;
const isAuthenticated = Boolean(req.cookies.token);
if (!isAuthenticated) {
return {
redirect: {
destination: '/login',
permanent: false
}
};
}
return { props: {} };
};

2. SSR + API-запросы

Ты можешь использовать любые fetch-запросы на сервере:

  • К REST API

  • К базам данных напрямую (например, через Prisma, MongoDB, Supabase и т.п.)

export const getServerSideProps = async () => {
const res = await fetch('http://localhost:3000/api/news');
const data = await res.json();
return { props: { data } };
};

3. SSR и производительность

  • SSR требует больше ресурсов на сервере, т.к. каждый запрос рендерит страницу.

  • Можно использовать CDN/Edge Functions/Cache-Control для балансировки нагрузки.

  • Next.js поддерживает кеширование, etag, Cache-Control в SSR-ответах.

Гидратация (Hydration)

После того как SSR-страница загружена в браузер, React "гидратирует" её:

  • связывает уже отрендеренный HTML с виртуальным DOM,

  • добавляет обработчики событий,

  • позволяет React-приложению стать интерактивным.

SSR в Next.js 13+ (App Router)

С переходом на App Router и серверные компоненты SSR стало ещё мощнее и гибче.

Особенности:

  • По умолчанию app/ папка использует серверные компоненты (.tsx компоненты рендерятся на сервере).

  • Асинхронные серверные компоненты (async function Page() {}) позволяют делать fetch прямо в JSX.

  • SSR встроен без необходимости явно использовать getServerSideProps.

Пример с App Router:

// app/profile/page.tsx
async function getUser() {
const res = await fetch('https://api.example.com/user', { cache: 'no-store' });
return res.json();
}
export default async function ProfilePage() {
const user = await getUser();
return <div>Hello, {user.name}</div>;
}

Инструменты и дополнения:

  • Middleware: позволяет обрабатывать запросы до SSR (например, аутентификацию).

  • NextAuth.js: для SSR-авторизации и сессий.

  • @next/font: для оптимизации шрифтов на сервере.

  • next/cache: для управления кешем данных.

SSR в сочетании с CDN и Edge Functions:

Next.js может запускать SSR не только на основном сервере, но и ближе к пользователю — на edge-функциях (например, Vercel Edge Functions). Это снижает задержки и ускоряет доставку страниц.

export const config = {
runtime: 'edge',
};

Next.js предоставляет высокоуровневый API для реализации SSR с минимумом ручной настройки и с глубокими возможностями кастомизации.