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.
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 ?
- Applications hautement interactives : Dashboards complexes avec beaucoup d’état partagé
- Real-time : Apps nécessitant WebSocket omniprésent
- Heavy client-side routing : SPAs avec navigation complexe
Quand utiliser les îles ?
- Sites de contenu : Blogs, documentation, portfolios
- Sites marketing : Landing pages avec quelques formulaires
- E-commerce : Pages produits avec panier dynamique
- Applications hybrides : Principalement statique avec zones interactives
Comparaison avec d’autres approches
| Approche | Bundle moyen | Complexité | Performance |
|---|---|---|---|
| SPA (React) | 200+ KB | Moyenne | Moyenne |
| SSR (Next.js) | 150+ KB | Haute | Moyenne |
| SSG (Gatsby) | 120+ KB | Haute | Bonne |
| Islands (Astro) | 10-30 KB | Faible | Excellente |
| Pure HTML | 0 KB | Très faible | Excellente |
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.