Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
В чем разница между SSR mode?
SSR (Server-Side Rendering) имеет несколько режимов выполнения, которые критически влияют на производительность, масштабируемость и пользовательский опыт приложения. Понимание различий между ними важно для правильной архитектуры.
Основные SSR режимы
1. Static Generation (SSG)
Static Generation - страницы генерируются во время сборки (build time):
// Next.js пример
export async function getStaticProps() {
const posts = await fetchPosts();
return {
props: { posts },
revalidate: 86400 // ISR: переизвлечь через 24 часа
};
}
export default function Blog({ posts }) {
return <div>{posts.map(p => <p key={p.id}>{p.title}</p>)}</div>;
}
// Результат: HTML файл генерируется один раз и переиспользуется для всех пользователей
Преимущества:
- Максимальная скорость (можно кэшировать на CDN)
- Минимальная нагрузка на сервер
- Отличная производительность
Недостатки:
- Долгое время сборки для больших сайтов (тысячи страниц)
- Сложно обновлять часто меняющиеся данные
- Все пользователи видят одинаковый контент
2. Server-Side Rendering (SSR)
Server-Side Rendering - страницы генерируются для каждого запроса на сервере:
// Next.js пример
export async function getServerSideProps(context) {
const { userId } = context.params;
const user = await fetchUser(userId);
return {
props: { user },
revalidate: 0 // Не кэшировать
};
}
export default function UserProfile({ user }) {
return <div>Welcome {user.name}!</div>;
}
// Результат: HTML генерируется для каждого запроса
Преимущества:
- Свежие данные для каждого пользователя
- Подходит для динамического контента
- Хорошо для SEO (поисковики видят полный HTML)
- Может быть персонализировано
Недостатки:
- Медленнее чем SSG (генерация для каждого запроса)
- Высокая нагрузка на сервер при популярности
- Время отклика зависит от скорости БД
3. Incremental Static Regeneration (ISR)
ISR - гибридный подход: генерирует статичные страницы, но переизвлекает их в фоне:
export async function getStaticProps() {
const posts = await fetchPosts();
return {
props: { posts },
revalidate: 60 // Переизвлечь страницу через 60 секунд
};
}
// Первый запрос: быстро возвращает старый HTML
// В фоне: генерирует новый HTML на основе свежих данных
// Второй запрос: возвращает новый HTML
Преимущества:
- Быстрота SSG в большинстве случаев
- Свежесть данных (через определенный интервал)
- Масштабируется без проблем
Недостатки:
- Может быть задержка в обновлении (до revalidate интервала)
- Требует настройки времени переизвлечения
- Нужна фоновая работа сервера
Практическое сравнение
// Сценарий 1: Блог с редко обновляемыми постами
// Решение: SSG + ISR
export async function getStaticProps() {
const posts = await fetchPosts();
return {
props: { posts },
revalidate: 3600 // Обновлять раз в час
};
}
// Сценарий 2: Профиль пользователя (персональный контент)
// Решение: SSR
export async function getServerSideProps(context) {
const { userId } = context.params;
const user = await fetchUser(userId);
return {
props: { user }
};
}
// Сценарий 3: Каталог товаров (много страниц, редкие обновления)
// Решение: SSG + ISR
export async function getStaticProps(context) {
const { productId } = context.params;
const product = await fetchProduct(productId);
return {
props: { product },
revalidate: 86400 // Обновлять раз в день
};
}
export async function getStaticPaths() {
// Какие пути генерировать при сборке
return {
paths: [
{ params: { productId: '1' } },
{ params: { productId: '2' } }
],
fallback: 'blocking' // При запросе неизвестного пути - SSR
};
}
Client-Side Rendering (CSR)
Хотя это не SSR, важно понимать отличие:
// CSR: рендер происходит в браузере
import { useEffect, useState } from 'react';
export default function Page() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(r => r.json())
.then(setData);
}, []);
if (!data) return <div>Loading...</div>;
return <div>{data.title}</div>;
}
// Проблемы:
// - Пустой HTML изначально (плохо для SEO)
// - Медленнее чем SSR (двойной запрос: HTML + API)
// - Может быть видна процесс загрузки
Performance сравнение
// Метрики для типичной страницы:
// SSG: 50ms - 100ms (из кэша CDN)
const ssg = {
ttfb: '50ms', // Time To First Byte
fcp: '80ms', // First Contentful Paint
lcp: '150ms' // Largest Contentful Paint
};
// ISR: 50ms (первый раз), затем обновляется
const isr = {
ttfb: '50ms (кэш) или 500ms (регенерация)',
fcp: '80ms (кэш) или 600ms (регенерация)',
lcp: '150ms (кэш) или 700ms (регенерация)'
};
// SSR: 200ms - 1000ms (зависит от БД)
const ssr = {
ttfb: '300-500ms',
fcp: '400-600ms',
lcp: '600-1000ms'
};
// CSR: 100ms (HTML) + 300ms (API) = 400ms+
const csr = {
ttfb: '100ms',
fcp: '500-800ms (из-за JS выполнения)',
lcp: '700-1200ms'
};
Выбор режима в Next.js
// pages/blog/[slug].tsx
// Вариант 1: SSG с ISR
export async function getStaticProps(context) {
const post = await fetchPost(context.params.slug);
return {
props: { post },
revalidate: 60 // Переизвлечь через минуту
};
}
export async function getStaticPaths() {
return {
paths: [{ params: { slug: 'hello-world' } }],
fallback: 'blocking' // На неизвестных путях: SSR
};
}
// Вариант 2: SSR
export async function getServerSideProps(context) {
const post = await fetchPost(context.params.slug);
return { props: { post } };
}
// Выбор зависит от:
// - Частоты обновлений
// - Количества уникальных страниц
// - Требований к свежести данных
// - Нагрузке на сервер
Рекомендации
Используй SSG + ISR для:
- Блогов и документации
- Каталогов товаров
- Статичного контента с редкими обновлениями
- Когда нужна максимальная скорость
Используй SSR для:
- Персонального контента (профили пользователей)
- Данных зависящих от cookies/headers
- Часто меняющихся данных
- Когда нужна максимальная свежесть
Используй CSR для:
- Админ-панелей (не нужен SEO)
- Интерактивных приложений
- Когда можно ждать загрузки JS
Гибридный подход (современный стандарт)
// Лучший паттерн: SSG/ISR + гидрация + Client-Side обновления
export async function getStaticProps() {
// SSG для быстрого первого запроса
const initialData = await fetchData();
return {
props: { initialData },
revalidate: 3600
};
}
export default function Page({ initialData }) {
const [data, setData] = useState(initialData);
// Обновляем данные в браузере, если нужно
useEffect(() => {
const interval = setInterval(
() => fetchFreshData().then(setData),
60000 // Проверять каждую минуту
);
return () => clearInterval(interval);
}, []);
return <div>{data.title}</div>;
}
// Результат: быстрая доставка + свежие данные = лучший UX
Итоговая таблица
| Режим | Скорость | Свежесть | Сложность | Масштабируемость |
|---|---|---|---|---|
| SSG | Отличная | Низкая | Простой | Отличная |
| ISR | Отличная | Хорошая | Средний | Отличная |
| SSR | Хорошая | Отличная | Средний | Средняя |
| CSR | Средняя | Хорошая | Простой | Хорошая |
Правильный выбор SSR режима - один из ключей к высокопроизводительному приложению.