Реализация Islands Architecture для веб-приложения

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация Islands Architecture для веб-приложения
Сложная
~3-5 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация Islands Architecture для веб-приложения

Islands Architecture — архитектурный паттерн, где страница состоит из статичного HTML-океана с изолированными «островами» интерактивности. Каждый остров — независимый компонент с собственным JS, который гидратируется отдельно, не зная о соседних островах.

Концепцию описал Джейсон Миллер (Preact) в 2020 году. Сегодня это основа Astro, Marko, и часть подхода в Qwik.

Архитектурная модель

Статичный HTML (сервер, нулевой JS):
┌─────────────────────────────────────┐
│ Header                              │  ← HTML
│  Logo | Nav links | ...             │
├─────────────────────────────────────┤
│ Hero section                        │  ← HTML
│  H1, изображение, CTA               │
├──────────────┬──────────────────────┤
│ Article text │  🏝️ Island:          │  ← JS только для острова
│  (HTML)      │  TableOfContents.tsx │
│              │  (sticky, highlight) │
├──────────────┴──────────────────────┤
│ 🏝️ Island: CommentSection.tsx       │  ← JS только для острова
│  (React, загружается при скролле)   │
├─────────────────────────────────────┤
│ Footer                              │  ← HTML
└─────────────────────────────────────┘

Итог: JS грузится только для 2 островов, не для всей страницы

Реализация в Astro

Astro — первый фреймворк с нативной поддержкой Islands:

---
// src/pages/blog/[slug].astro
import type { GetStaticPaths } from 'astro';
import { getCollection } from 'astro:content';

// Серверные компоненты — .astro файлы без JS на клиенте
import BaseLayout from '@/layouts/BaseLayout.astro';
import ArticleHero from '@/components/ArticleHero.astro';
import Prose from '@/components/Prose.astro';

// Острова — React/Vue/Svelte компоненты с директивами
import TableOfContents from '@/islands/TableOfContents.tsx';
import CommentSection from '@/islands/CommentSection.tsx';
import ShareButtons from '@/islands/ShareButtons.svelte';
import NewsletterSignup from '@/islands/NewsletterSignup.vue';

export const getStaticPaths: GetStaticPaths = async () => {
  const posts = await getCollection('blog', p => !p.data.draft);
  return posts.map(post => ({ params: { slug: post.slug }, props: { post } }));
};

const { post } = Astro.props;
const { Content, headings } = await post.render();
---

<BaseLayout title={post.data.title} description={post.data.description}>
  <ArticleHero post={post} />

  <div class="article-layout">
    <!-- Остров 1: интерактивное оглавление -->
    <!-- Загружается только когда браузер простаивает -->
    <TableOfContents headings={headings} client:idle />

    <article>
      <Prose>
        <Content />
      </Prose>
    </article>
  </div>

  <!-- Остров 2: кнопки шаринга -->
  <!-- Загружается только при появлении в viewport -->
  <ShareButtons
    url={Astro.url.href}
    title={post.data.title}
    client:visible
  />

  <!-- Остров 3: комментарии -->
  <!-- Загружается только при появлении в viewport, задержка 500ms -->
  <CommentSection
    articleId={post.id}
    client:visible={{ rootMargin: '0px 0px 200px 0px' }}
  />

  <!-- Остров 4: подписка на рассылку -->
  <!-- Загружается немедленно — в fold -->
  <NewsletterSignup client:load />
</BaseLayout>

Острова с межостровной коммуникацией

Острова изолированы — у них нет общего контекста React. Для коммуникации используются:

Nano Stores (рекомендуется для Astro):

// src/stores/cart.ts
import { atom, computed } from 'nanostores';
import { persistentAtom } from '@nanostores/persistent';

export const cartItems = persistentAtom<CartItem[]>('cart', [], {
  encode: JSON.stringify,
  decode: JSON.parse,
});

export const cartCount = computed(cartItems, items => items.length);
export const cartTotal = computed(cartItems, items =>
  items.reduce((sum, item) => sum + item.price * item.qty, 0)
);

export function addToCart(product: Product) {
  const items = cartItems.get();
  const existing = items.find(i => i.id === product.id);
  if (existing) {
    cartItems.set(items.map(i => i.id === product.id ? { ...i, qty: i.qty + 1 } : i));
  } else {
    cartItems.set([...items, { ...product, qty: 1 }]);
  }
}
// islands/CartIcon.tsx — React остров
import { useStore } from '@nanostores/react';
import { cartCount } from '@/stores/cart';

export function CartIcon() {
  const count = useStore(cartCount);
  return (
    <a href="/cart" className="relative">
      <ShoppingCartIcon />
      {count > 0 && <span className="badge">{count}</span>}
    </a>
  );
}
<!-- islands/AddToCartButton.svelte — Svelte остров -->
<script>
  import { addToCart } from '@/stores/cart';
  export let product;

  let loading = false;

  async function handleAdd() {
    loading = true;
    addToCart(product);
    loading = false;
  }
</script>

<button on:click={handleAdd} disabled={loading}>
  {loading ? 'Добавляем...' : 'В корзину'}
</button>

Оба острова (React и Svelte) работают с одним хранилищем. Изменение в одном — немедленно отражается в другом.

Нативные браузерные события:

// Универсальная шина событий через CustomEvent
export function emit<T>(event: string, detail: T) {
  window.dispatchEvent(new CustomEvent(event, { detail, bubbles: true }));
}

export function on<T>(event: string, handler: (detail: T) => void) {
  const wrapped = (e: CustomEvent<T>) => handler(e.detail);
  window.addEventListener(event, wrapped as EventListener);
  return () => window.removeEventListener(event, wrapped as EventListener);
}

// В острове 1
emit('product:added', { id: product.id, name: product.name });

// В острове 2
useEffect(() => {
  return on<{ id: string; name: string }>('product:added', ({ name }) => {
    showToast(`${name} добавлен в корзину`);
  });
}, []);

Рендеринг островов на нескольких фреймворках

Astro поддерживает несколько рендерер-плагинов одновременно:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import vue from '@astrojs/vue';
import svelte from '@astrojs/svelte';
import preact from '@astrojs/preact';

export default defineConfig({
  integrations: [
    react(),           // Для существующих React-компонентов
    vue(),             // Для Vue-компонентов из библиотеки клиента
    svelte(),          // Для лёгких интерактивных виджетов
    preact({ compat: true }), // Preact как замена React для лёгких островов
  ],
});

На практике: разные фреймворки для разных целей в рамках одного сайта без конфликтов.

Производительность: цифры

Измерения на реальных проектах после миграции на Islands Architecture:

Метрика До (Full React SSR) После (Astro Islands)
Initial JS 180–250 KB 15–40 KB
TTI 3.2s 0.8s
TBT 480ms 60ms
Lighthouse Performance 62 96

Разброс зависит от количества и сложности островов.

Ограничения паттерна

Islands Architecture не подходит для:

  • SPA-приложений — там нужно единое состояние между многими компонентами
  • Дашбордов — слишком много интерактивности, острова теряют изоляцию
  • Страниц, где всё интерактивно — выигрыш минимален

Идеальный случай: контентный сайт с несколькими интерактивными блоками на странице.

Сроки реализации

  • Неделя 1–2: аудит существующего сайта, выявление интерактивных компонентов, настройка Astro + рендерер-плагины
  • Неделя 3: перенос статичных страниц, разбивка на острова с директивами гидратации
  • Неделя 4: межостровная коммуникация через nano stores, тестирование изоляции
  • Неделя 5: измерение Core Web Vitals, сравнение с baseline, оптимизация директив
  • Неделя 6: деплой (Cloudflare Pages / Netlify), Lighthouse CI, финальная документация