Angular

Инкрементальная гидрация

Полная гидрация оживляет всё дерево компонентов сразу: даже футер и виджеты внизу страницы тянут свой JavaScript при загрузке, конкурируя за главный поток. Инкрементальная гидрация делит работу: серверный HTML показывается целиком, но JavaScript подгружается и гидрирует каждый участок лишь тогда, когда он нужен - по прокрутке, клику или в простое. Меньше кода в первые секунды, лучше отзывчивость.

  • Длинные страницы: верх гидрируется сразу, низ - по прокрутке
  • Виджеты вне сгиба: чат, карта, графики гидрируются on interaction или on viewport
  • Контентные сайты: статичная часть остаётся серверным HTML без лишнего JS
  • Улучшение INP: главный поток не забит гидрацией невидимого
  • Экономия трафика: код невидимых блоков не скачивается, пока до них не дошли

Предварительные знания

  • SSR и полная гидрация: provideClientHydration, рассинхрон DOM
  • Блоки @defer и их триггеры: on viewport, on interaction, on idle
  • Понимание Core Web Vitals: LCP, INP, TBT

Гидрация по частям

Полная гидрация (Angular 16) решила проблему мерцания, но оживляла всё дерево сразу, нагружая главный поток. Команда соединила гидрацию с механизмом @defer: блок может рендериться на сервере как обычный HTML и гидрироваться лениво по триггеру. Инкрементальная гидрация появилась как developer preview в Angular 19 (ноябрь 2024) и стабилизировалась к Angular 20-21. Ключевое отличие от обычного @defer: содержимое всё равно рендерится на сервере, а не показывается через placeholder.

Чем отличается от полной гидрации

Полная гидрация оживляет всё дерево компонентов в момент загрузки: весь JavaScript скачивается и выполняется, даже для блоков вне зоны видимости. Инкрементальная гидрация откладывает эту работу для отдельных участков. Сервер всё равно рендерит их HTML, но клиентский JS присоединяется к участку только по триггеру.

  • Полная гидрация — Весь серверный DOM оживляется сразу при загрузке. Весь JavaScript компонентов скачивается и выполняется на старте, нагружая главный поток
  • Инкрементальная гидрация — Серверный HTML показан целиком, но JavaScript участка скачивается и гидрирует его лишь по триггеру. Невидимое не нагружает старт

Важное отличие от обычного @defer: при инкрементальной гидрации содержимое уже отрендерено сервером и видно пользователю в виде HTML. Обычный @defer на чистом клиенте до триггера показывает placeholder, а не реальный контент.

Инкрементальная гидрация требует включённой полной гидрации как основы (provideClientHydration). Это надстройка, которая делает базовую гидрацию ленивой по участкам, а не отдельный независимый механизм.

Чем инкрементальная гидрация отличается от обычного @defer на клиентском приложении?

Триггеры hydrate

Инкрементальная гидрация записывается как блок @defer с ключевым словом hydrate и триггером. Содержимое рендерится сервером, а триггер решает, когда скачать JS и гидрировать участок. Доступны те же триггеры, что у @defer: on viewport, on interaction, on idle, on hover, on timer.

Здесь app-comments отрендерен сервером и виден как HTML, но его обработчики присоединятся только когда секция попадёт в область видимости. app-rating гидрируется при первом клике. До этого участки остаются статичным серверным HTML без своего JavaScript.

Триггер hydrate never означает, что участок никогда не гидрируется: его JavaScript не скачивается вовсе, он навсегда остаётся серверным HTML. Это подходит для полностью статичных блоков вроде юридического футера, который не требует интерактивности.

Когда срабатывает любой триггер hydrate, Angular гидрирует не только сам блок, но и вложенные в него инкрементальные блоки, обеспечивая консистентность. Поэтому планировать границы участков стоит по реальным зонам интерактивности.

Что делает триггер hydrate never на блоке @defer?

Выигрыш в Core Web Vitals

Главная нагрузка при загрузке - выполнение JavaScript на главном потоке. Полная гидрация оживляет всё сразу, что раздувает Total Blocking Time и ухудшает отзывчивость (INP). Инкрементальная гидрация переносит гидрацию невидимого на потом, освобождая главный поток в критические первые секунды.

МетрикаЧто измеряетЭффект инкрементальной гидрации
LCPВремя до отрисовки крупнейшего элементаНе ухудшается: контент уже в серверном HTML
TBTВремя блокировки главного потокаСнижается: меньше JS выполняется на старте
INPЗадержка отклика на взаимодействиеУлучшается: поток свободнее, отклик быстрее
Объём JS на стартеСкачанный JavaScript при загрузкеМеньше: код невидимых участков откладывается

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

Инкрементальная гидрация - инструмент для крупных страниц с большим количеством интерактивности вне сгиба. Для маленькой страницы, где всё видно сразу, разбиение на участки добавит сложности без заметного выигрыша. Сначала стоит профилировать, где именно главный поток забит.

На какую метрику Core Web Vitals инкрементальная гидрация влияет сильнее всего за счёт разгрузки главного потока?

Связь с другими темами

Инкрементальная гидрация - стык SSR-гидрации и @defer:

  • SSR и гидрация — База: полная гидрация, поверх которой добавляется ленивость по участкам
  • @defer — Тот же синтаксис и триггеры, но с ключевым словом hydrate и серверным рендером содержимого

Итог

  • Инкрементальная гидрация гидрирует участки страницы по отдельности, а не всё дерево сразу
  • Она строится на @defer с триггерами hydrate: hydrate on viewport, hydrate on interaction, hydrate on idle
  • В отличие от обычного @defer, содержимое рендерится на сервере как полноценный HTML, а не показывается плейсхолдером
  • До гидрации участок остаётся статичным серверным HTML, его JS не скачивается
  • Выигрыш в Core Web Vitals: меньше TBT и лучше INP, потому что главный поток не занят гидрацией невидимого

Связанные уроки

  • ng-34-ssr-hydration — Инкрементальная гидрация надстраивается над полной гидрацией и SSR из предыдущего урока
  • ng-33-defer — Механизм построен на тех же блоках и триггерах @defer
Инкрементальная гидрация

0

1

Войти