Astro 4.12: Server Islands

Автор
Erika
Matthew Phillips

Вышел Astro 4.12! В релизе — первый экспериментальный релиз Server Islands, новое решение для сочетания высокопроизводительного статического HTML и динамических серверных компонентов. Также улучшения пагинации и подсветки синтаксиса.

Основные новинки:

Чтобы обновить существующий проект, используйте CLI @astrojs/upgrade. Или обновите вручную:

# Рекомендуется:
npx @astrojs/upgrade
# Вручную:
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

Experimental: Server Islands

В 2021 Astro принёс islands architecture в мейнстрим — «острова» интерактивных клиентских компонентов при статически сгенерированной странице.

С Server islands мы расширяем эту архитектуру на сервер. Server islands упрощают сочетание высокопроизводительного статического HTML и динамических серверных компонентов.

На странице может быть контент, который:

  • полностью статичен и никогда не меняется;
  • динамически из БД, меняется реже, чем деплои;
  • персонализирован для каждого пользователя.

Сейчас нужно выбрать одну стратегию кэширования для всего — для авторизованных страниц обычно это отсутствие кэша. Server islands дают лучшее из обоих миров.

A diagram showing the server island population parts of the page from the server.

Server islands — для самого динамичного контента: аватар, корзина, отзывы. При отложенной загрузке страницу можно агрессивнее кэшировать.

Пользователи — авторизованные и нет — мгновенно видят критичные части страницы на Edge CDN. Fallback-контент виден короткое время, затем загружаются динамические islands.

Каждый island загружается независимо — медленный island (например, с legacy backend) не задержит остальной персонализированный контент.

Performance

Мы создали server-islands.com — демо по мотивам Next.js Partial Prerendering, в стиле Astro. Server Islands много общего с PPR, особенно в цели повысить кэшируемость страниц.

Metricspartialprerendering.comserver-islands.com
TTFB 0.838s 0.766s
FCP 1.740s 1.251s
LCP 1.740s 1.405s
TBT 0.093s 0.018s
Source WebPageTest WebPageTest

server-islands.com стабильно быстрее при повторных запусках — на 20% быстрее Largest Contentful Paint, одна из Core Web Vitals Google, влияющих на UX и SEO.

В отличие от PPR, Server Islands запрашивают origin из браузера, а не с сервера. Islands отрисовываются раньше, но могут завершиться позже PPR.

Оба подхода лучше всего для сайтов, где основной контент кэшируется на edge — ecommerce, но не лента соцсети. При edge-кэше ожидание запроса island минимально.

Мы уверены в этом компромиссе как в лучшем балансе производительности для пользователей Astro — UX и Core Web Vitals без специальной backend-инфраструктуры.

Portability

Server islands спроектированы с учётом переносимости. Не зависят от серверной инфраструктуры — работают с любым хостингом: Node.js в Docker или serverless.

Реализация в основном на этапе сборки — контент компонента заменяется небольшим скриптом.

Islands с server:defer выделяются в отдельные маршруты, которые скрипт запрашивает в runtime. Компромисс: island не получает head-start рендеринга через edge, но цифры производительности в пользу более простого подхода.

Trying out Server Islands

Мы ещё полируем функцию, но попробовать Server Islands можно в Astro 4.12:

import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
output: 'hybrid',
adapter: netlify(),
experimental: {
serverIslands: true,
},
})

Server islands работают на сервере — нужен 'server' или 'hybrid' output. После включения используйте server:defer на любом компоненте:

<Avatar server:defer>
<GenericUserImage slot="fallback" />
</Avatar>

При сборке Astro пропускает компонент и вставляет скрипт плюс контент slot="fallback". В браузере компоненты и props запрашиваются у специального endpoint, который рендерит и возвращает HTML.

Server Islands — обычные Astro-компоненты с middleware, slots, client: islands.

Getting involved

У Server Islands есть активный RFC. Мы финализируем детали — вероятно, добавим encrypted props. Попробуйте 4.12 и поделитесь мнением!

Added first and last URLs to pagination data

Хелпер paginate() теперь возвращает свойства first и last в данных пагинации — URL первой и последней страницы. Спасибо @tsawada!

Added support for the Shiki’s defaultColor option

Опция defaultColor переопределяет inline-стили темы, добавляя только CSS-переменные для гибкости с несколькими цветовыми темами. Настраивается в Shiki config для всего сайта или в <Code> для отдельного блока. Спасибо @madcampos!

New inferRemoteSize function

В Astro 4.4 мы добавили inferSize для Image, Picture и getImage(). Благодаря @itsmatteomanf теперь есть inferRemoteSize() — размер удалённого изображения без этих компонентов или getImage().

Полезно для генерации разных плотностей или когда нужны размеры для стилей.

---
import { inferRemoteSize, Image } from 'astro:assets';
const { width, height } = await inferRemoteSize('https://...');
---
<Image src={"https://..."} width={width / 2} height={height} densities={[1.5, 2]} />

Some more things

Как обычно, Astro 4.12 включает исправления и улучшения, не вошедшие в этот пост! Полные release notes.

Особая благодарность @sarah11918, @Fryuni, @ARipeAppleByYoursTruly и всем остальным контрибьюторам релиза.