lenec ru

← все посты

Astro framework: строим контентный сайт с островами интерактивности

15K

Если вы строите контентный сайт — блог, документацию, лендинг — и устали от того, что 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-компоненты продолжат работать, просто станут «островами».

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.