Сайт из документации, блога и лендинга редко нуждается в мегабайтах JavaScript. Но стоит добавить корзину или фильтр, как фреймворк тянет гидратацию на все страницы. Astro предлагает компромисс: HTML собирается заранее, а JavaScript загружается только для явно помеченных интерактивных блоков — островов.

Как работают острова

Компонент .astro выполняется на этапе сборки и превращается в HTML. Если внутри нужен React, Vue или Svelte, его подключают директивой client. Без директивы компонент отрендерится статически, а его скрипты в браузер не попадут.

  • client:load — гидрировать сразу, для важных элементов.
  • client:idle — после загрузки страницы, когда браузер свободен.
  • client:visible — когда блок появился в зоне видимости.
  • client:only — только на клиенте, без серверного HTML.

Чем позже гидрирование, тем меньше работы при первом рендере. Но у client:visible есть цена: до появления блока интерфейс не отвечает. Для кнопки «купить» это плохо, для виджета комментариев — нормально.

Граница острова проходит по компоненту, а не по странице. Внутри одного острова может быть целое дерево React-компонентов, и весь этот код загрузится вместе. Поэтому крупные виджеты делят на несколько независимых островов, чтобы не тянуть лишнее.

Создание проекта

Мастер задаёт имя, шаблон и настройки TypeScript. Минимальный шаблон не тащит лишних зависимостей.

npm create astro@latest blog -- --template minimal
cd blog
npm install
npm run dev

Разработка идёт на локальном сервере с горячей перезагрузкой, а сборка складывает готовый сайт в dist. Предпросмотр проверяет именно собранную версию, а не dev-режим.

npm run build
npm run preview
npx astro check
npx astro --version

Структура и маршруты

Файлы в src/pages становятся маршрутами. Динамические страницы используют квадратные скобки и getStaticPaths: на этапе сборки Astro вызывает функцию и создаёт по странице на каждый элемент.

---
export async function getStaticPaths() {
  return [
    { params: { slug: 'pervaya' } },
    { params: { slug: 'vtoraya' } },
  ];
}
const { slug } = Astro.params;
---

Общий каркас выносят в layout: там заголовок, навигация, подвал и слот. Страницы подключают его и передают содержимое. Так проще держать метатеги и canonical в одном месте.

Контент-коллекции

Markdown-файлы удобно хранить в src/content и описывать схему. Схема проверяет поля на сборке: забытая дата или строка вместо массива тегов остановят билд, а не сломают страницу в проде.

import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';

const blog = defineCollection({
  loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
  schema: z.object({
    title: z.string(),
    date: z.coerce.date(),
    draft: z.boolean().default(false),
  }),
});

export const collections = { blog };

На странице коллекцию читают через getCollection, фильтруют черновики и сортируют по дате. Функция render отдаёт компонент и заголовки для оглавления.

---
import { getCollection } from 'astro:content';
const posts = (await getCollection('blog', ({ data }) => !data.draft))
  .sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
---

Если контент приходит из CMS, вместо glob используют загрузчик под API. Схема остаётся той же, поэтому шаблоны не меняются.

Остров с React

Интеграция ставится одной командой и добавляет зависимости. Дальше компонент импортируют и помечают директивой.

npx astro add react
npm run build
---
import Counter from '../components/Counter.jsx';
---
<Counter client:visible />

Такой остров скачает код только при прокрутке до блока. Если виджет нужен сразу, меняют директиву на client:load, но следят за размером бандла: каждая библиотека внутри острова едет в браузер целиком.

Картинки и производительность

Компонент Image из astro:assets оптимизирует изображения на сборке: меняет формат, режет размеры, добавляет width и height. Это убирает сдвиг вёрстки и лишние килобайты. Для локальных файлов достаточно импорта.

---
import { Image } from 'astro:assets';
import cover from '../assets/cover.jpg';
---
<Image src={cover} alt="Обложка" widths={[480, 960]} />

Шрифты подключают локально, а не через внешний CDN: меньше запросов и никаких сторонних соединений. Критические стили инлайнят, остальные грузят отдельно. Prefetch ускоряет переходы по ссылкам, но увеличивает трафик — включайте осознанно.

Сборка и публикация

Статический вариант — это каталог dist, который можно отдать любым веб-сервером. Кэширование хешированных файлов ставят надолго, а HTML — ненадолго, чтобы обновления доходили быстро.

server {
    root /var/www/blog/dist;
    index index.html;
    error_page 404 /404.html;
    location /_astro/ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    location / {
        try_files $uri $uri/ =404;
    }
}

Если нужен серверный рендеринг, подключают адаптер Node и запускают entry.mjs под systemd или в контейнере. Часть маршрутов можно оставить статическими, а личный кабинет рендерить на сервере. Перед публикацией прогоняйте сборку на отдельном стенде: так ошибки путей и кэша видны до того, как их увидят читатели.

Диагностика

Основные проблемы видны на сборке и в консоли браузера. astro check ловит типы в .astro и TypeScript, а предупреждения о гидратации обычно означают несовпадение разметки на сервере и клиенте.

  • Страница пустая — проверьте base и пути к ассетам при деплое в подкаталог.
  • Компонент не реагирует — забыта директива client.
  • Дублирование стилей — разные версии интеграции.
  • Медленный первый рендер — слишком много островов с client:load.

Смотрите размер JS на конкретной странице, а не общий бандл. Один тяжёлый виджет на главной может стоить дороже всего остального сайта.

Для проверки доступности прогоняйте страницы с отключённым JavaScript: контент должен оставаться читаемым, а навигация — работать. Это же упражнение показывает, какие блоки действительно зависят от гидратации, а какие можно оставить статическими навсегда.

Чек-лист

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

Итог

Astro хорошо подходит контентным сайтам: быстрый первый рендер, минимум JavaScript и понятная работа с Markdown. Острова позволяют добавлять интерактивность точечно, не переписывая всё на фреймворк. Начните с одной страницы и замерьте вес JS — обычно после этого желание тащить SPA на весь сайт пропадает.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте