Найти в Дзене
Палитра будней 📆

CSR, SSR, SSG, ISR, LCP, FID, CLS, Гидрация, Прогрессивная гидрация и Island Architecture

В современной веб-разработке производительность и пользовательский опыт стали критически важными факторами успеха приложения. За последние годы мы прошли путь от классического клиентского рендеринга к сложным гибридным моделям. В этой статье мы разберем ключевые концепции, которые должен понимать каждый frontend-разработчик. Что это: Полностью браузерный рендеринг. Сервер отдает практически пустой HTML-файл с подключенными JavaScript-библиотеками, а браузер скачивает, парсит и выполняет JavaScript, который затем рендерит интерфейс. <!-- Типичный index.html в CSR приложении -->
<!DOCTYPE html>
<html>
<head>
<title>Мое приложение</title>
</head>
<body>
<div id="root"></div> <!-- Пустой контейнер -->
<script src="bundle.js"></script> <!-- Весь код тут -->
</body>
</html> Плюсы: Минусы: Когда использовать: Админки, дашборды, приложения, где SEO неважен. Что это: Классический подход, где сервер генерирует полный HTML для каждой страницы и отдает его браузеру в готовом
Оглавление

В современной веб-разработке производительность и пользовательский опыт стали критически важными факторами успеха приложения. За последние годы мы прошли путь от классического клиентского рендеринга к сложным гибридным моделям. В этой статье мы разберем ключевые концепции, которые должен понимать каждый frontend-разработчик.

1. CSR (Client-Side Rendering) - Клиентский рендеринг.

Что это: Полностью браузерный рендеринг. Сервер отдает практически пустой HTML-файл с подключенными JavaScript-библиотеками, а браузер скачивает, парсит и выполняет JavaScript, который затем рендерит интерфейс.

<!-- Типичный index.html в CSR приложении -->
<!DOCTYPE html>
<html>
<head>
<title>Мое приложение</title>
</head>
<body>
<div id="root"></div> <!-- Пустой контейнер -->
<script src="bundle.js"></script> <!-- Весь код тут -->
</body>
</html>

Плюсы:

  • Богатая интерактивность после загрузки
  • Плавные переходы между страницами (SPA)
  • Минимальная нагрузка на сервер

Минусы:

  • Долгая первоначальная загрузка (белый экран)
  • Плохая SEO (поисковики видят пустую страницу)
  • Зависимость от JavaScript

Когда использовать: Админки, дашборды, приложения, где SEO неважен.

2. SSR (Server-Side Rendering) - Серверный рендеринг

Что это: Классический подход, где сервер генерирует полный HTML для каждой страницы и отдает его браузеру в готовом виде.

// Express.js пример SSR
app.get('/product/:id', (req, res) => {
const product = getProductFromDB(req.params.id);
const html = `
<html>
<head><title>${product.name}</title></head>
<body>
<h1>${product.name}</h1>
<p>${product.description}</p>
<!-- Готовый HTML сразу -->
</body>
</html>
`;
res.send(html);
});

Плюсы:

  • Мгновенный первый контент (no white screen)
  • Идеальная SEO-оптимизация
  • Работает без JavaScript

Минусы:

  • Медленный TTFB (Time To First Byte) при сложной логике
  • Высокая нагрузка на сервер
  • Меньше интерактивности

3. SSG (Static Site Generation) - Статическая генерация

Что это: HTML генерируется на этапе сборки и раздается как статические файлы.

// Next.js пример SSG
export async function getStaticProps() {
const products = await getAllProducts();
return {
props: { products },
revalidate: 3600 // ISR: перегенерировать раз в час
};
}

export default function HomePage({ products }) {
return (
<div>
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}

Плюсы:

  • Молниеносная загрузка (CDN)
  • Бесплатная хостинг (GitHub Pages, Netlify)
  • Идеальная безопасность (нет сервера)

Минусы:

  • Нет динамических данных без пересборки
  • Долгая сборка для больших сайтов

4. ISR (Incremental Static Regeneration) - Инкрементальная статическая регенерация

Что это: Продвинутая версия SSG, где страницы могут обновляться постфактум без полной пересборки.

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

  1. При первом запросе генерируется и кэшируется страница
  2. Последующие запросы получают кэшированную версию
  3. В фоне запускается регенерация по расписанию или триггеру
  4. Новая версия заменяет старую для следующих пользователей

Пример сценария:

  • Блог: новые статьи добавляются без пересборки всего сайта
  • Каталог товаров: цены обновляются раз в час
  • Новостной сайт: главная страница обновляется каждые 5 минут

5. Core Web Vitals - Ключевые показатели производительности

Google ввел три ключевых метрики для оценки пользовательского опыта:

LCP (Largest Contentful Paint) - Загрузка самого большого элемента

Мера скорости загрузки. Должен быть менее 2.5 секунд.

// Оптимизации для LCP:
// 1. Предзагрузка ключевых ресурсов

<link rel="preload" href="hero-image.jpg" as="image">
// 2. Оптимизация изображений

<img src="image.jpg" loading="lazy" width="800" height="600">
// 3. Минимизация блокирующего CSS/JS

FID (First Input Delay) - Задержка первого ввода

Мера отзывчивости. Должен быть менее 100 мс.

// Улучшение FID:
// 1. Разделение кода на чанки

const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
// 2. Отложенная загрузка не критичного JS

// 3. Веб-воркеры для тяжелых вычислений

CLS (Cumulative Layout Shift) - Совокупное смещение макета

Мера визуальной стабильности. Должен быть менее 0.1.

<!-- Предотвращение CLS: -->
<img width="300" height="200" src="image.jpg">
<!-- Всегда указывать размеры! -->

<div style="min-height: 300px;">
<!-- Резервируем место для лениво грузящегося контента -->
</div>

6. Гидрация (Hydration) - "Оживление" статического HTML

Что это: Процесс, когда React "оживляет" статический HTML, добавляя к нему интерактивность.

// После SSR/SSG мы получаем статический HTML:
<div id="root">
<button>Нажми меня</button> <!-- Статическая кнопка -->
</div>

// React гидратирует, добавляя обработчики:
<div id="root">
<button onClick={() => console.log('Clicked!')}>
Нажми меня
</button>
</div>

Проблема традиционной гидрации:

  • Блокирует главный поток
  • Может быть медленной на слабых устройствах
  • Перегидрация всего приложения при навигации

7. Прогрессивная гидрация (Progressive Hydration)

Что это: Умная гидрация, которая происходит частями, а не всей страницей сразу.

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

  1. Критические компоненты гидратируются сразу
  2. Невидимые/неинтерактивные компоненты откладываются
  3. Гидрация по приоритету или при взаимодействии

// Пример с React 18 и Suspense
function App() {
return (
<div>
{/* Критичный компонент */}
<CriticalSection />

{/* Отложенная гидрация */}
<Suspense fallback={<Spinner />}>
<HeavyInteractiveComponent />
</Suspense>

{/* Гидрация по видимости */}
<Suspense fallback={<Placeholder />}>
<LazyComponent />
</Suspense>
</div>
);
}

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

  • Улучшенный TTI (Time To Interactive)
  • Меньше блокировок главного потока
  • Более плавный пользовательский опыт

8. Island Architecture (Архитектура "Островов")

Что это: Парадигма, где страница состоит из независимых "островов" интерактивности в море статического HTML.

// Пример с Astro.js (поддерживает Island Architecture)
---
// Статический компонент
import ProductCard from '../components/ProductCard.astro'
// Интерактивный "остров"
import CartCounter from '../components/CartCounter.jsx'
---

<div class="product-page">
<!-- Статическая часть -->
<ProductCard product={product} />

<!-- Интерактивный "остров" -->
<CartCounter client:load /> <!-- Загружается с приоритетом -->

<!-- Отложенный "остров" -->
<ProductReviews client:visible /> <!-- При появлении в viewport -->
</div>

Ключевые принципы:

  1. Минимум интерактивности: Только там, где действительно нужно
  2. Изоляция: Острова не зависят друг от друга
  3. Прогрессивность: Загрузка по мере необходимости

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

  • Экстремально быстрая загрузка
  • Минимальный JavaScript
  • Независимое обновление компонентов
  • Отличные Core Web Vitals