Гідратація React та рендеринг на стороні сервера (SSR)
Що таке рендеринг на стороні сервера (SSR)?
SSR рендерить компоненти React у HTML на сервері та надсилає повністю згенерований HTML до браузера. Браузер відображає HTML миттєво (швидкий перший контентний малюнок), після чого React бере на себе управління, щоб зробити його інтерактивним.
Потік SSR + Гідратація
1. Користувач запитує сторінку
2. Сервер рендерить React → HTML рядок
3. HTML надсилається до браузера → користувач бачить контент миттєво
4. Браузер завантажує пакет React JS
5. React "гідратує" HTML → прикріплює обробники подій
6. Сторінка тепер повністю інтерактивнаЩо таке гідратація?
Гідратація — це процес, коли React прикріплює обробники подій та стан до існуючого HTML, згенерованого на сервері, без повторного рендерингу. React "перепрофілює" DOM замість того, щоб створювати його з нуля.
// Сервер рендерить цей HTML:
// <button>Натиснуто 0 разів</button>
// Клієнт гідратує — прикріплює обробник onClick до існуючої кнопки
// Нові елементи DOM не створюються — React повторно використовує серверний HTMLSSR проти CSR проти SSG
| Підхід | Коли генерується HTML | Продуктивність | SEO |
|---|---|---|---|
| CSR (Клієнтська сторона) | У браузері | Повільний FCP, швидка навігація | Погано |
| SSR (Серверна сторона) | При кожному запиті | Швидкий FCP, витрати на сервер | Чудово |
| SSG (Статична генерація) | Під час збірки | Найшвидший | Чудово |
| ISR (Інкрементальна) | Збірка + повторна валідація | Швидко + свіжо | Чудово |
Помилки гідратації
Коли HTML сервера не відповідає тому, що React очікує на клієнті:
// ❌ Викликає невідповідність гідратації
function Clock() {
return <p>{new Date().toLocaleTimeString()}</p>;
// Сервер: "10:00:00 AM"
// Клієнт: "10:00:01 AM" — РІЗНІ!
}
// ✅ Виправлення: рендерити час тільки на клієнті
function Clock() {
const [time, setTime] = useState<string>("");
useEffect(() => {
setTime(new Date().toLocaleTimeString());
const interval = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
return () => clearInterval(interval);
}, []);
return <p>{time || "Завантаження..."}</p>;
}Загальні причини помилок гідратації
- Використання
Date.now(),Math.random()у рендері - API, доступні тільки в браузері (
window,localStorage) у рендері - Різні дані на сервері та клієнті
- Неправильне вкладення HTML (
<p><div>...</div></p>) - Розширення браузера, що змінюють DOM
Вибіркова гідратація (React 18)
React 18 може гідратувати різні частини сторінки незалежно за допомогою Suspense:
import { Suspense } from "react";
function Page() {
return (
<div>
<Header /> {/* Гідратується миттєво */}
<Suspense fallback={<Spinner />}>
<HeavySidebar /> {/* Гідратується, коли готовий */}
</Suspense>
<Suspense fallback={<Skeleton />}>
<Comments /> {/* Може гідратуватися незалежно */}
</Suspense>
</div>
);
}З вибірковою гідратацією:
- React може гідратувати незалежно від блокування — інші частини залишаються інтерактивними
- Якщо користувач натискає на ще не гідратовану секцію, React пріоритизує її
Стрімінг SSR
React 18 також представив стрімінг — надсилання HTML частинами:
// Сервер поступово стрімить HTML
// 1. Надає <html>, <head>, <Header /> миттєво
// 2. Коли дані готові, стрімить <MainContent />
// 3. Коли завантажуються коментарі, стрімить <Comments />
// Кожна межа Suspense є точкою стрімінгу
<Suspense fallback={<Loading />}>
<SlowComponent /> {/* Стрімиться, коли готовий */}
</Suspense>Переваги:
- Користувачі бачать контент швидше (прогресивне завантаження)
- Час до першого байта (TTFB) швидший
- Немає необхідності чекати на ВСІ дані перед надсиланням відповіді
Важливо:
SSR генерує HTML на сервері для швидкого початкового відображення та SEO. Гідратація потім робить його інтерактивним на клієнті. React 18 покращив це за допомогою вибіркової гідратації та стрімінгу SSR, що дозволяє неприв'язане прогресивне рендеринг. Будьте обережні з помилками гідратації, викликаними невідповідностями між контентом сервера та клієнта.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.