Серверные островки
Серверные островки позволяют рендерить по запросу динамические или персонализированные «островки» по отдельности, не жертвуя производительностью остальной части страницы.
Это значит, что посетитель раньше увидит самые важные части страницы, а основной контент можно будет кешировать агрессивнее, что ускорит работу сайта.
Компоненты серверных островков
Заголовок раздела «Компоненты серверных островков»Серверный островок — это обычный компонент Astro, рендерящийся на сервере, которому указано отложить рендеринг до тех пор, пока его содержимое не станет доступно.
Страница будет отрендерена сразу с указанным резервным контентом в качестве заглушки. Затем собственное содержимое компонента запрашивается на клиенте и отображается, когда оно готово.
Установив адаптер для выполнения отложенного рендеринга, добавьте директиву server:defer (EN) любому компоненту на странице, чтобы превратить его в отдельный островок:
---import Avatar from '../components/Avatar.astro';---<Avatar server:defer />Такие компоненты могут делать всё, что обычно доступно на странице, рендерящейся по запросу через адаптер, — например, запрашивать контент и обращаться к кукам:
---import { getUserAvatar } from '../sessions';const userSession = Astro.cookies.get('session');const avatarURL = await getUserAvatar(userSession);---<img alt="Аватар пользователя" src={avatarURL} />Передача пропсов серверным островкам
Заголовок раздела «Передача пропсов серверным островкам»Пропсы, передаваемые компонентам серверных островков, должны быть сериализуемыми: то есть их можно преобразовать в формат, пригодный для передачи по сети или для хранения. Кроме того, Astro сериализует не все типы сериализуемых структур данных. Поэтому на то, что можно передать серверному островку в качестве пропсов, есть ограничения.
В частности, компонентам с директивой server:defer нельзя передавать функции, так как они не сериализуются. Объекты с циклическими ссылками также не сериализуемы.
Поддерживаются следующие типы пропсов:
простой объект, number, string, Array, Map, Set, RegExp, Date, BigInt, URL, Uint8Array, Uint16Array, Uint32Array и Infinity
Резервный контент серверного островка
Заголовок раздела «Резервный контент серверного островка»Используя атрибут server:defer на компоненте для откладывания его рендеринга, вы можете «подставить» контент загрузки по умолчанию через встроенный именованный слот "fallback".
Резервный контент отрендерится вместе с остальной страницей при её первоначальной загрузке и будет заменён содержимым компонента, когда оно станет доступно.
Чтобы добавить резервный контент, укажите slot="fallback" на дочернем элементе (другом компоненте или HTML-элементе), переданном компоненту серверного островка:
---import Avatar from '../components/Avatar.astro';import GenericAvatar from '../components/GenericAvatar.astro';---<Avatar server:defer> <GenericAvatar slot="fallback" /></Avatar>Резервным контентом могут быть, например:
- Обобщённый аватар вместо аватара пользователя.
- UI-заглушки, например собственные сообщения.
- Индикаторы загрузки, например спиннеры.
Как это работает
Заголовок раздела «Как это работает»Реализация серверных островков происходит в основном на этапе сборки, когда содержимое компонента подменяется небольшим скриптом.
Каждый островок с директивой server:defer выделяется в собственный специальный маршрут, который этот скрипт запрашивает во время выполнения. При сборке сайта Astro пропустит компонент и вставит на его место скрипт, а также контент, помеченный slot="fallback".
Когда страница загрузится в браузере, эти компоненты будут запрошены со специального эндпоинта, который отрендерит их и вернёт HTML. Благодаря этому пользователи мгновенно увидят самые важные части страницы. Резервный контент будет виден непродолжительное время, пока не загрузятся динамические островки.
Каждый островок загружается независимо от остальных. Это значит, что более медленный островок не задержит появление остального персонализированного контента.
Этот паттерн рендеринга создавался переносимым. Он не зависит от какой-либо серверной инфраструктуры, поэтому будет работать с любым хостингом — от сервера Node.js в Docker-контейнере до бессерверного провайдера на ваш выбор.
Кеширование
Заголовок раздела «Кеширование»Данные для серверных островков запрашиваются через GET-запрос, а пропсы передаются в виде зашифрованной строки в query-параметрах URL. Это позволяет кешировать данные с помощью HTTP-заголовка Cache-Control, используя его стандартные директивы.
Однако браузер ограничивает длину URL максимумом в 2048 байт из практических соображений и во избежание проблем типа «отказ в обслуживании». Если из-за строки запроса URL превышает этот лимит, Astro вместо этого отправит POST-запрос со всеми пропсами в теле.
POST-запросы не кешируются браузерами, поскольку используются для отправки данных и могли бы привести к проблемам с целостностью данных или безопасностью. Поэтому существующая логика кеширования в вашем проекте перестанет работать. По возможности передавайте серверным островкам только необходимые пропсы и не отправляйте целые объекты данных и массивы, чтобы строка запроса оставалась небольшой.
Доступ к URL страницы в серверном островке
Заголовок раздела «Доступ к URL страницы в серверном островке»В большинстве случаев компонент серверного островка может получить информацию о странице, которая его рендерит, через передачу пропсов, как в обычных компонентах.
Однако серверные островки выполняются в собственном изолированном контексте вне запроса страницы. Astro.url и Astro.request.url в компоненте серверного островка возвращают URL вида /_server-islands/Avatar, а не URL текущей страницы в браузере. Кроме того, при предварительном рендеринге страницы у вас не будет доступа, например, к query-параметрам, чтобы передать их как пропсы.
Чтобы получить информацию из URL страницы, проверьте заголовок Referer — он содержит адрес страницы, загружающей островок в браузере:
---const referer = Astro.request.headers.get("Referer");
if (!referer) { throw new Error("Referer header is missing");}
const url = new URL(referer);const productId = url.searchParams.get("product");---Повторное использование ключа шифрования
Заголовок раздела «Повторное использование ключа шифрования»Astro использует криптографию для шифрования пропсов, передаваемых серверным островкам, защищая чувствительные данные от случайного раскрытия. Шифрование опирается на новый случайный ключ, который генерируется при каждой сборке и встраивается в серверный бандл.
Большинство хостингов автоматически позаботятся о синхронизации фронтенда и бэкенда. Однако постоянный ключ шифрования может понадобиться, если вы используете скользящие развёртывания (rolling deployments), мультирегиональный хостинг или CDN, кеширующий страницы с серверными островками.
В окружениях со скользящими развёртываниями (например, Kubernetes), где фронтенд-ресурсы (шифрующие пропсы) и бэкенд-функции (расшифровывающие их) могут временно использовать разные ключи, а также когда CDN всё ещё отдаёт страницы, собранные со старым ключом, зашифрованные пропсы серверного островка расшифровать не удастся.
В таких ситуациях сгенерируйте с помощью Astro CLI многоразовый закодированный ключ шифрования и задайте его переменной окружения в сборочном окружении:
astro create-keyИспользуйте полученное значение для настройки переменной окружения ASTRO_KEY (например, в файле .env) и добавьте её в настройки сборки CI/CD или хостинга. Так в собираемом бандле всегда будет использоваться один и тот же ключ, а шифрование и расшифровка останутся синхронизированными.