Astro framework: строим контентный сайт с островами интерактивности
Если вы строите контентный сайт — блог, документацию, лендинг — и устали от того, что Next.js тащит на клиент сотни килобайт JavaScript ради одной кнопки, пора посмотреть на Astro. Этот фреймворк по умолчанию отдаёт чистый HTML без единого байта JS, а интерактивность добавляется точечно через «острова» (islands).
Что такое Astro и зачем он нужен
Astro — веб-фреймворк для контентных сайтов. Главная идея: zero JavaScript by default. Страницы рендерятся при билде в статический HTML. Никакого гидрейшна всей страницы, никакого клиентского роутера.
Сравните с Next.js: даже с Server Components вы получаете клиентский бандл для навигации и React-рантайм. В Astro клиентский JS появляется только там, где вы явно попросили. Результат — Lighthouse 100/100 становится нормой.
Islands Architecture: управляем гидрацией
Страница — «море» статического HTML, а интерактивные компоненты — отдельные «острова», которые гидрируются независимо. Вы управляете моментом гидрации через директивы:
client:load— гидрация сразу при загрузке. Для критичных элементов: навигация, формы.client:visible— гидрация при попадании во viewport (IntersectionObserver). Для комментариев, виджетов внизу.client:idle— гидрация когда браузер свободен (requestIdleCallback). Для чат-ботов, аналитики.client:media— гидрация по медиа-запросу. Мобильное меню только на узких экранах.
---
import Counter from '../components/Counter.tsx';
import Comments from '../components/Comments.svelte';
---
<article>...статический контент...</article>
<!-- Гидрируется сразу -->
<Counter client:load />
<!-- Гидрируется при скролле -->
<Comments client:visible />
Без директивы client:* компонент рендерится только на сервере — ноль JS на клиенте.
React, Vue и Svelte в одном проекте
Киллер-фича Astro — компоненты из разных фреймворков в одном проекте. Форма на React, карусель на Svelte, дашборд на Vue:
npx astro add react
npx astro add svelte
npx astro add vue
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import svelte from '@astrojs/svelte';
import vue from '@astrojs/vue';
export default defineConfig({
integrations: [react(), svelte(), vue()]
});
Каждый остров загружает только рантайм своего фреймворка. Svelte-компонент вообще без рантайма — только скомпилированный код. Это позволяет постепенно мигрировать между фреймворками.
Content Collections и типизация
Для контентных сайтов Astro предлагает Content Collections — управление контентом с валидацией через Zod-схемы и автогенерацией TypeScript-типов.
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/data/blog' }),
schema: z.object({
title: z.string(),
pubDate: z.coerce.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };
Запрашиваем посты с полной типизацией:
---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog', ({ data }) => {
return data.draft !== true;
});
---
<ul>
{posts.map(post => (
<li><a href={`/blog/${post.id}`}>{post.data.title}</a></li>
))}
</ul>
Опечатка в frontmatter — ошибка на этапе билда, а не в продакшене.
Деплой: static vs SSR
Astro поддерживает два режима. Static (по умолчанию) — сайт генерируется при билде, деплоится куда угодно. SSR — страницы рендерятся по запросу, нужен для динамики и авторизации.
npx astro add vercel # или netlify
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'server',
adapter: vercel(),
});
Можно комбинировать: большинство страниц статические, отдельные маршруты — серверные. Используйте export const prerender = true/false на уровне страниц.
Подводные камни
- Нет клиентского роутера. Переходы — полная перезагрузка (View Transitions API частично решает проблему).
- Состояние между островами не шарится. Нужны nanostores или signals.
- Не подходит для SPA. Если приложение — сплошная интерактивность (Figma, Google Docs), Astro не ваш выбор.
Вывод
Astro идеально ложится на задачи, где контент первичен. Zero JS by default даёт производительность из коробки, а Islands Architecture позволяет добавлять интерактивность точечно. Если вы используете Next.js для статического блога — попробуйте Astro. Ваши React-компоненты продолжат работать, просто станут «островами».