Architecture

Islands Architecture : Comprendre le paradigme révolutionnaire d'Astro

Plongée technique dans l'architecture en îles d'Astro, qui permet d'hydrater sélectivement les composants pour des performances optimales.

Rubio
6 min de lecture
#Astro #Architecture #Performance #JavaScript

Qu’est-ce que l’Islands Architecture ?

L’Islands Architecture (architecture en îles) est un paradigme architectural introduit par Katie Sylor-Miller en 2019 et popularisé par Astro. Cette approche révolutionnaire change fondamentalement la manière dont nous pensons l’hydratation des applications web.

Le problème des frameworks traditionnels

Les frameworks JavaScript classiques (React, Vue, Angular) hydratent l’intégralité de la page :

┌─────────────────────────────────┐
│                                 │
│     Tout est JavaScript         │
│                                 │
│  ┌──────┐  ┌──────┐  ┌──────┐ │
│  │ Nav  │  │ Hero │  │ Form │ │
│  └──────┘  └──────┘  └──────┘ │
│                                 │
│  ┌──────┐  ┌──────┐  ┌──────┐ │
│  │ Card │  │ List │  │Footer│ │
│  └──────┘  └──────┘  └──────┘ │
│                                 │
└─────────────────────────────────┘
   Bundle: 200+ KB JavaScript

Conséquences :

  • Bundle JavaScript volumineux (150-300 KB)
  • Temps d’hydratation long (1-3 secondes)
  • Performance mobile dégradée
  • Coût d’exécution élevé sur CPU faible

La solution : Les îles

Astro adopte une approche différente. Seuls les composants vraiment interactifs sont hydratés :

┌─────────────────────────────────┐
│                                 │
│     HTML statique rapide       │
│                                 │
│  ┌──────┐  ┌──────┐  ┌──────┐ │
│  │ Nav  │  │ Hero │  │ Form │ │  ← île interactive
│  └──────┘  └──────┘  └──────┘ │
│                                 │
│  ┌──────┐  ┌──────┐  ┌──────┐ │
│  │ Card │  │ List │  │Footer│ │  ← île interactive
│  └──────┘  └──────┘  └──────┘ │
│                                 │
└─────────────────────────────────┘
   Bundle: 12 KB JavaScript

Implémentation dans Astro

1. Composants statiques par défaut

Par défaut, tous les composants Astro sont rendus côté serveur et aucun JavaScript n’est envoyé :

---
// Composant purement statique
const title = "Mon Portfolio";
const items = ["Projet 1", "Projet 2", "Projet 3"];
---

<section class="projects">
  <h2>{title}</h2>
  <ul>
    {items.map(item => <li>{item}</li>)}
  </ul>
</section>

<!-- Résultat : 0 KB de JavaScript -->

2. Hydratation sélective avec directives

Astro offre plusieurs directives client pour contrôler l’hydratation :

client:load - Hydratation immédiate

Charge et hydrate le composant dès que possible :

---
import InteractiveCounter from './Counter.tsx';
---

<InteractiveCounter client:load />

Utilisation : Composants critiques au-dessus de la ligne de flottaison.

client:idle - Hydratation différée

Hydrate quand le navigateur est inactif (utilise requestIdleCallback) :

<ChatWidget client:idle />

Utilisation : Composants non critiques mais visibles.

client:visible - Hydratation au scroll

Hydrate uniquement quand le composant entre dans le viewport :

<Comments client:visible />

Utilisation : Contenu en bas de page, lazy loading.

client:media - Hydratation conditionnelle

Hydrate selon une media query :

<MobileMenu client:media="(max-width: 768px)" />

Utilisation : Composants spécifiques mobile/desktop.

client:only - Rendu côté client uniquement

Ne rend pas le composant côté serveur :

<BrowserOnlyFeature client:only="react" />

Utilisation : Composants dépendant d’APIs navigateur.

Exemple concret : Un blog performant

Structure classique (React SSR)

// app.jsx - Tout est JavaScript
export default function BlogPost({ post, comments, related }) {
  return (
    <Layout>
      <Header />              {/* ← Hydraté */}
      <Article post={post} /> {/* ← Hydraté */}
      <Sidebar />             {/* ← Hydraté */}
      <Comments data={comments} /> {/* ← Hydraté */}
      <RelatedPosts posts={related} /> {/* ← Hydraté */}
      <Footer />              {/* ← Hydraté */}
    </Layout>
  );
}

Bundle total : ~180 KB JavaScript

Structure optimisée (Astro Islands)

---
import Header from './Header.astro';        // Statique
import Article from './Article.astro';      // Statique
import Sidebar from './Sidebar.astro';      // Statique
import Comments from './Comments.tsx';      // Île interactive
import RelatedPosts from './Related.astro'; // Statique
import Footer from './Footer.astro';        // Statique

const { post, comments, related } = Astro.props;
---

<Layout>
  <Header />
  <Article post={post} />
  <Sidebar />
  
  <!-- Seul composant hydraté -->
  <Comments data={comments} client:visible />
  
  <RelatedPosts posts={related} />
  <Footer />
</Layout>

Bundle total : ~8 KB JavaScript (composant Comments uniquement)

Mesures de performance réelles

Test sur un article de blog avec formulaire de commentaires :

Avant (Next.js SSR)

Performance Metrics:
┌─────────────────────┬──────────┐
│ Metric              │ Value    │
├─────────────────────┼──────────┤
│ First Load JS       │ 187 KB   │
│ TTI (Time to Inter) │ 2.4s     │
│ FCP                 │ 1.1s     │
│ Lighthouse Score    │ 78/100   │
└─────────────────────┴──────────┘

Après (Astro Islands)

Performance Metrics:
┌─────────────────────┬──────────┐
│ Metric              │ Value    │
├─────────────────────┼──────────┤
│ First Load JS       │ 11 KB    │
│ TTI (Time to Inter) │ 0.6s     │
│ FCP                 │ 0.3s     │
│ Lighthouse Score    │ 100/100  │
└─────────────────────┴──────────┘

Amélioration :

  • 94% moins de JavaScript
  • 4x plus rapide (TTI)
  • Score parfait Lighthouse

Patterns avancés

1. Communication entre îles

Les îles peuvent communiquer via des événements personnalisés :

// CartButton.tsx
function CartButton() {
  const addToCart = () => {
    window.dispatchEvent(new CustomEvent('cart:add', {
      detail: { productId: 123 }
    }));
  };
  
  return <button onClick={addToCart}>Ajouter</button>;
}

// CartCount.tsx
function CartCount() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    const handler = () => setCount(c => c + 1);
    window.addEventListener('cart:add', handler);
    return () => window.removeEventListener('cart:add', handler);
  }, []);
  
  return <span>{count}</span>;
}
<CartButton client:load />
<CartCount client:load />

2. Shared State avec Nano Stores

Pour un état partagé plus robuste :

// stores/cart.ts
import { atom } from 'nanostores';

export const cartItems = atom([]);
// CartButton.tsx
import { useStore } from '@nanostores/react';
import { cartItems } from '../stores/cart';

function CartButton() {
  const items = useStore(cartItems);
  
  const addItem = () => {
    cartItems.set([...items, newItem]);
  };
  
  return <button onClick={addItem}>Add ({items.length})</button>;
}

Limitations et considérations

Quand éviter les îles ?

  1. Applications hautement interactives : Dashboards complexes avec beaucoup d’état partagé
  2. Real-time : Apps nécessitant WebSocket omniprésent
  3. Heavy client-side routing : SPAs avec navigation complexe

Quand utiliser les îles ?

  1. Sites de contenu : Blogs, documentation, portfolios
  2. Sites marketing : Landing pages avec quelques formulaires
  3. E-commerce : Pages produits avec panier dynamique
  4. Applications hybrides : Principalement statique avec zones interactives

Comparaison avec d’autres approches

ApprocheBundle moyenComplexitéPerformance
SPA (React)200+ KBMoyenneMoyenne
SSR (Next.js)150+ KBHauteMoyenne
SSG (Gatsby)120+ KBHauteBonne
Islands (Astro)10-30 KBFaibleExcellente
Pure HTML0 KBTrès faibleExcellente

Conclusion

L’Islands Architecture d’Astro représente un changement de paradigme fondamental dans le développement web moderne. En inversant l’approche traditionnelle (tout dynamique par défaut), Astro permet de créer des sites ultra-performants tout en conservant la possibilité d’ajouter de l’interactivité là où c’est nécessaire.

Cette architecture est particulièrement adaptée aux projets orientés contenu où la majorité des composants sont statiques. Pour ces cas d’usage, les gains de performance sont spectaculaires :

  • Chargement 4-10x plus rapide
  • Coûts de bande passante réduits
  • Expérience mobile optimale
  • Accessibilité améliorée (fonctionne sans JavaScript)

L’avenir du web passe par une approche plus réfléchie de l’utilisation de JavaScript, et Astro montre la voie avec son architecture en îles.

Ressources complémentaires