Эволюция персонального сайта: от React Discord-визитки до островной архитектуры Astro 5
Эволюция персонального сайта: от React Discord-визитки до островной архитектуры Astro 5
Персональный сайт разработчика редко остается статичным артефактом: он непрерывно эволюционирует вместе с профессиональным опытом, стеком и требованиями к производительности. Однако фундаментальный выбор архитектуры определяет ключевые свойства ресурса — скорость первой отрисовки (FCP), точность поискового индексирования (SEO), надежность предпросмотра в социальных сетях (OpenGraph) и удобство долгосрочной поддержки архива технических кейсов.
В данном материале разобран путь развития персонального сайта через три поколения: от простого HTML+CSS, через интерактивную визитку React-Discord-Business-Card и до современной платформы OneHeka Portfolio на базе Astro 5 и островной архитектуры (Islands Architecture).
1. Хронология поколений: от статики к островам
Каждая итерация решала задачи своего времени, постепенно выявляя ограничения выбранного стека:
[ Поколение 1: Статический HTML + CSS ]
Простая посадочная страница, минимальный функционал, отсутствие интерактивности
│
▼ (Потребность в интерактиве и эстетике Discord)
[ Поколение 2: React Discord Business Card (SPA) ]
React, Vite/CRA, CSS/Framer Motion, имитация Discord-профиля
│
▼ (Масштабирование: блог, кейсы, i18n, оптимизация FCP и SEO)
[ Поколение 3: OneHeka Portfolio (Astro 5 + React 19 Islands) ]
Astro 5, Tailwind CSS v4, React 19 (острова), Content Collections,
поддержка 4 языков (RTL/LTR), 100/100 Lighthouse
Сравнительный срез трех поколений
| Параметр | Поколение 1: HTML+CSS | Поколение 2: React Discord Card | Поколение 3: OneHeka Portfolio |
|---|---|---|---|
| Стек | Чистый HTML5, CSS3 | React, Vite, Tailwind, Framer Motion | Astro 5, React 19, Tailwind v4, Zod |
| Рендеринг | Статический файл | Клиентский SPA (CSR) | Статическая генерация (SSG) + Острова |
| Базовый вес страницы | ~5–10 КБ | ~250–400 КБ (JS-бандл) | ~15–30 КБ (Чистый HTML + CSS) |
| First Contentful Paint (FCP) | 0.2 с | 1.4–2.4 с | 0.1–0.3 с |
| Интерактивность | Отсутствует | Полная (но тяжелая) | Точечная (через директивы client:*) |
| SEO & OpenGraph | Статический | Проблемный (пустой <div id="root">) |
Нативный SSG для 4 языков |
| Масштабируемость контента | Ручная верстка | Громоздкий стейт и роуты | Типобезопасные Content Collections |
2. Поколение 2: React Discord Business Card и лимиты SPA
Вторая версия проекта создавалась с фокусом на визуальную аутентичность интерфейса Discord: анимированная плашка профиля, бейджи, статус активности, интерактивные всплывающие карточки и контактные ссылки.
Архитектурные ограничения классического React SPA
Хотя решение выглядело эффектно, при попытке превратить визитку в полноценное портфолио с блогом и техническими разборами проявились ключевые недостатки Single Page Application:
- Задержка первого отображения (FCP & TTI):
Браузер получал пустой HTML-каркас (
<div id="root"></div>) и был вынужден ждать загрузки, парсинга и исполнения всего JS-бандла React перед тем, как пользователь увидит первый байт контента. - Ненадежный OpenGraph и SEO: Поисковые краулеры и парсеры превью в мессенджерах (Telegram, Discord, Twitter) часто считывали пустую страницу без динамически сформированных метаданных конкретной статьи.
- Раздувание кодовой базы:
Добавление многостраничности через
react-router-dom, локализации через громоздкие JSON-словари и ленивых импортов (React.lazy) неоправданно усложняло проект.
3. Парадигма Astro 5: Островная архитектура и Zero-JS
При проектировании третьей версии — OneHeka Portfolio — был совершен переход на Astro 5. В основу легла концепция Astro Islands:
- По умолчанию все страницы (статьи, списки проектов, шапка, футер) компилируются во время сборки в статический HTML и CSS без клиентского рантайма JavaScript.
- Компоненты React подключаются точечно как изолированные «острова» с явным указанием стратегии гидратации:
---
import { TableOfContents } from "@/components/molecules/table-of-contents";
import { ShareButton } from "@/components/molecules/share-button";
import { CommandMenu } from "@/components/molecules/command-menu";
import MainLayout from "@/layouts/main.astro";
const { headings, lang, title, description } = Astro.props;
---
<MainLayout title={title} description={description} lang={lang}>
<!-- Статический контент: чистый семантический HTML, 0 КБ JS -->
<article class='prose min-w-0 max-w-full'>
<slot />
</article>
<!-- Интерактивные острова React гидратируются независимо -->
<TableOfContents headings={headings} lang={lang} client:load />
<ShareButton lang={lang} client:load />
<CommandMenu lang={lang} client:idle />
</MainLayout>
Стратегии гидратации островов:
client:load— компонент гидратируется сразу при загрузке (глобальный скроллбарCustomScrollbar, оглавлениеTableOfContents).client:idle— гидратация откладывается до освобождения основного потока (палитра командCommandMenu, кнопка шаринга).client:visible— скрипты загружаются только при попадании компонента в область видимости (viewport).
4. Типобезопасный контент: Content Collections и Zod
Управление статьями и кейсами реализовано через встроенный загрузчик Content Collections (src/content.config.ts), гарантирующий строгую валидацию схем метаданных на этапе компиляции:
import { defineCollection, z } from "astro:content";
import { glob } from "astro/loaders";
const blog = defineCollection({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
tags: z.array(z.string()).optional().default([]),
lang: z.enum(['ru', 'en', 'zh', 'ae']).default('ru')
})
})
export const collections = { blog }
Любая ошибка в метаданных Markdown (отсутствие обязательного поля, неверный формат даты или неподдерживаемый язык) моментально прерывает сборку с указанием конкретной строки, гарантируя целостность структуры сайта в продакшене.
5. Интернационализация (i18n): 4 языка и нативный RTL
В OneHeka Portfolio реализована нативная многоязычность:
- 🇷🇺 Русский (
ru) - 🇬🇧 Английский (
en) - 🇨🇳 Китайский (
zh) - 🇦🇪 Арабский (
ae) — с полноценной правосторонней версткой (dir="rtl").
В отличие от SPA, где локали подгружаются через клиентские хранилища, Astro генерирует полностью статические страницы для каждого языка со сформированными тегами hreflang и каноническими ссылками.
6. Современный стек: Tailwind CSS v4, Geist Font и React Aria
Визуальная экосистема сайта построена на современных инженерных решениях:
- Tailwind CSS v4 с компилятором на базе Vite, обеспечивающим молниеносный HMR.
- Geist Variable Font от Vercel для идеальной четкости текста и читаемости кода.
- React Aria Components для гарантированной доступности (a11y), поддержки скринридеров и фокус-менеджмента.
- Палитра команд Cmd+K на базе
cmdkс автоопределением операционной системы (Mac / Windows) и плавной модальной анимацией.
7. Ключевые инженерные выводы
- SPA не подходит для контентных ресурсов: Использование чистого клиентского React для блогов и портфолио неоправданно раздувает бандл и ухудшает FCP.
- Островная архитектура — золотой стандарт: Astro 5 объединяет привычный DX экосистемы React с производительностью и легкостью чистого HTML.
- Типобезопасность от кода до контента: Использование Zod для схем статей и TypeScript для компонентов исключает класс ошибок с битыми данными еще на этапе сборки.