Что означает гидратация
Термин гидратация
часто встречается в разговорах о JavaScript фреймворках.
Для ясности поясню.
JavaScript-фреймворк Next.js, основанный на React, умеет рендерить и гидрировать на стороне сервера, поэтому начнём с него, зная, что другие крупные фреймворки делают это тоже. Я ценю ясность документации по самому React:
В React
гидратация— это то, как Reactприкрепляетсяк существующему HTML, который уже был отрисован React в серверной среде. Во время гидратации React попытается прикрепить слушателей событий к существующей разметке и взять на себя рендеринг приложения на клиенте.
Но сначала начнём с рендеринга только на стороне клиента. Допустим, у нас есть инвентарь с фруктами. В цикле создаём кнопки, которые при нажатии показывают инвентарь. Ну, знаете, как в любом реальном приложении.
export default function FruitPage() {
const inventory = [
{
name: "Apple",
quantity: 10
},
{
name: "Orange",
quantity: 8
},
{
name: "Banana",
quantity: 27
}
];
return (
<div className="box">
<h2>Check Fruit Quantities</h2>
{inventory.map((fruit) => {
return (
<button
onClick={() => {
alert(`There are ${fruit.quantity} ${fruit.name}s.`);
}}
key={fruit.name}
>
{fruit.name}
</button>
);
})}
</div>
);
}
Закину это в CodePen, который не будет выполнять никаких шагов по сборке и просто отрисует это на стороне клиента:
HTML, который браузер получает для этой страницы, иногда называют пустой оболочкой
. Это HTML-документ, но в нем нет реального содержимого, которое мы собирались туда поместить. Мы получаем следующее:
<div id="root"></div>
Клиентское приложение рендерится внутри него, когда оно готово. Не собираюсь говорить, что в мире нет места рендерингу только на стороне клиента. Но скажу, что в целом он не идеален, и всё чаще не используется по умолчанию. Почему не идеально? Если JavaScript не загружается по какой-либо причине, веб-сайта вообще не существует. И есть множество причин, по которым JavaScript не загружается (гораздо больше, чем HTML), например, ошибка выбрасывает исключение, в сети произошёл сбой, это долго загружающийся большой файл и пользователь намеренно или ненамеренно блокирует его и т. д.
Если мы запустим вместо этого готовый билд Next.js, в котором есть шаг сборки, то HTML-вывод будет выглядеть следующим образом:
Я выделил минифицированный HTML, чтобы показать, как код написанный в React/JSX, попадает в HTML, обслуживаемый приложением.
Это гораздо лучше! Контент отображается непосредственно в HTML в первом ответе от сервера. Браузер может работать с ним и получать его немедленно. И любой программный метод получения содержимого по URL (например, бот, curl и т. д.) будет успешным.
Затем JavaScript загружает и гидрирует этот HTML. Помните, как на кнопках были обработчики onClick
? Эта интерактивность не будет присутствовать на первом HTML-рендере сайта. Это не идеально (и, возможно, делает кнопки плохим примером для SSR), но суть в том, что контент там есть. Например, можно говорить обо всем содержимом важной маркетинговой лендинг-страницы.
Компромиссы
Здесь есть свои компромиссы. Накладываем ещё один фреймворк на наш фреймворк и добавляем процесс сборки. Добавляем зависимости и, следовательно, долгосрочную хрупкость нашей системы. Но в большинстве случаев передача настоящего HTML
браузеру считается хорошей вещью, и я буду официально утверждать, что вы должны предоставлять HTML с контентом браузерам с серверов.
Можно утверждать, что использование фреймворка, использующего SSR и гидратации, приводит к более сложному коду. Всегда нужно думать и кодить с учётом того, что компонент может быть отображён как на сервере, так и на клиенте. Вы пишете JavaScript, и он может казаться клиентским. Вы можете обратиться к объекту window или методу на нем и получить по запястью, что этого не существует в контексте сервера. Поэтому вы пишете условия, чтобы обойти это, что может вызвать различные проблемы. Возможно, придётся получать данные, ориентируясь на сервер, и, возможно, обрабатывать их иначе, чем на клиенте. Не говоря о том, что нужен сервер! Приложения с чисто клиентским рендерингом можно обслуживать со статического хостинга, который, скорее всего, будет дешёвым или бесплатным.
Что может пойти не так
Наиболее вероятная проблема — несоответствие HTML. Поскольку мы начали с Next.js, вот статья NextJS Hydration Errors: Causes, Fixes, Tips, демонстрирующая множество ошибок гидратации этого фреймворка. В процессе разработки, скорее всего, столкнётесь с показательными ошибками на всю страницу с ошибками гидратации, потому что фреймворк очень хочет, чтобы вы их исправили, и это необходимо сделать. Как правило, в продакшн-сборке сайта ошибки на стороне пользователя сглаживаются, и сайт остаётся функциональным. Проблема в том, что тогда сайт буквально выполняет двойную работу, и SSR страница полностью сдувается, из-за проблем на стороне клиента. Я видел, как ошибки, связанные с гидратацией, полностью ломали сайт, так что опять же: возможно, здесь имеет место хрупкость. Решение подобных проблем — это работа, которая может привести к новым сложностям.
Неужели использование JavaScript-фреймворка с SSR обязательно требует гидратацию
Если вам вообще не нужна интерактивность, то нет. Мне лично нравится компонентная модель создания сайтов с компонентами на JavaScript, даже если это в основном статический контент. Astro отлично справляется с этой задачей, но и другие фреймворки можно настроить так, чтобы не выводить JavaScript (тем самым пропуская процесс гидратации).
В одной из статей было подмечено: Гидратация — это чисто накладные расходы
.
…гидратация — это восстановление обработчиков событий путём загрузки и повторного выполнения всех компонентов в SSR/SSG-рендеринге HTML. Сайт отправляется клиенту дважды, один раз в виде HTML, а второй — в виде JavaScript.
Действительно, накладные расходы. Возможно, не идеальный вариант, но, вероятно, он того стоит.
Фреймворк Quik позволяет полностью избежать гидратации с помощью концепции, которую его разработчики назвали возобновляемость
. Честно говоря, я не знаю его настолько хорошо, чтобы полностью понять все компромиссы (обещаю: компромиссы есть всегда). Но если вы уверены, что гидратация — ваша главная проблема, на него стоит взглянуть.
Вам также следует пить больше воды.