ASTRO
#astro#islands#client-visible#viewport#performance

Astro: островок с client:visible — гидратация при появлении в viewport

Директива client:visible запускает гидратацию островка только когда элемент попадает в зону видимости. Меньше JS при загрузке.

Как использовать

  1. Добавьте к островку директиву client:visible вместо client:load: <PricingCalc client:visible />.
  2. Гидратация произойдёт при первом появлении элемента в зоне видимости (Intersection Observer).
  3. Используйте для виджетов ниже первого экрана: калькуляторы, формы, галереи, фильтры.

В Astro островки можно гидратировать не только при загрузке страницы, но и при появлении в viewport. Директива client:visible запускает гидратацию только когда элемент попадает в зону видимости (через Intersection Observer). Проблема: виджет внизу страницы с client:load тянет свой JS при первой загрузке — увеличивается время до интерактивности и объём начального JS. Симптомы: тяжёлая первая загрузка, долгий FCP при большом числе островков. Ниже — как использовать client:visible для виджетов ниже первого экрана, проверка и когда оставить client:load по документации.

Решение

client:visible гидратирует островок только когда он попадает в viewport. Подходит для виджетов ниже первого экрана: калькуляторы, формы, галереи, фильтры. Меньше JS при загрузке страницы.

Страница с виджетом ниже fold:

---
// src/pages/pricing.astro
import Layout from '../layouts/BaseLayout.astro';
import PricingCalc from '../components/PricingCalc.tsx';
---
<Layout title="Стоимость">
  <section>
    <h2>Калькулятор стоимости</h2>
    <p>Виджет загрузится и станет интерактивным только когда пользователь доскроллит сюда.</p>
    <PricingCalc client:visible />
  </section>
</Layout>

До срабатывания Intersection Observer островок отображается как статический HTML (то, что компонент отрендерил при сборке). Для интерактива «above the fold» используйте client:load.

Когда использовать client:visible:

  • Виджет (калькулятор, форма, фильтры) находится ниже первого экрана.
  • Нужно уменьшить объём JS при первой загрузке.
  • Контент в основном статический, интерактив точечный.

Проверка

  1. Загрузка страницы — откройте страницу с островком с client:visible. В Network при первой загрузке не должен сразу подгружаться чанк этого островка (или он может отложенно подгрузиться). После прокрутки до блока виджета должен запроситься соответствующий JS и виджет станет интерактивным.

  2. Прокрутка до виджета — доскролльте до секции с компонентом. Кнопки, поля формы или другие интерактивные элементы должны начать реагировать. До этого виджет может отображаться как статичная разметка (если компонент что-то рендерит при build).

  3. Диагностика: виджет не гидратируется — проверьте консоль браузера на ошибки. Убедитесь, что директива указана как client:visible (без пробелов). Для отладки можно временно заменить на client:load и убедиться, что сам компонент и интеграция работают.

  4. Порог срабатывания — по умолчанию Astro использует небольшой rootMargin (элемент считается видимым чуть раньше входа в viewport). При необходимости тонкой настройки смотрите документацию по директиве или используйте свой wrapper с Intersection Observer.

Типичные ошибки

  • Виджет above the fold с client:visible — если интерактивный блок в шапке или сразу на экране, пользователь может кликнуть до появления в viewport, и гидратация ещё не произойдёт. Для контента «в первом экране» используйте client:load.
  • Ожидание «пустого» места — до гидратации островок показывает статический вывод компонента при сборке. Если компонент при SSR не рендерит контент (или рендерит placeholder), пользователь увидит пустое место до скролла. Убедитесь, что компонент при build отдаёт хотя бы заглушку или скелетон.
  • Нет интеграции фреймворка — как и для client:load, для React/Vue/Svelte должна быть включена соответствующая интеграция в astro.config.mjs.

Где применять

  • Prod / dev: длинные страницы с калькуляторами, формами, галереями, фильтрами ниже первого экрана; лендинги с точечными интерактивными блоками.
  • Оптимизация: когда на странице несколько островков и не все видны сразу, замена части client:load на client:visible снижает начальный объём JS и ускоряет первую отрисовку.

Связанные сниппеты: Островок React с client:load, Статический вывод по умолчанию, Content Collections: фильтр и сортировка.