Server Islands sont la fonctionnalité phare d’Astro 5. Elles résolvent un problème récurrent : comment garder les bénéfices d’un site essentiellement statique (perf, SEO, coût hébergement bas) tout en injectant des fragments dynamiques personnalisés (panneau utilisateur, dernier prix, panier, statut commande) sans tout passer en SSR ? Voici le tutoriel complet pour utiliser Server Islands en 2026 (informations vérifiées en avril 2026, susceptibles d’évoluer).
Voir notre guide pratique Astro 5.
Le problème résolu
Avant Astro 5, vous aviez deux choix : page statique (zéro perso) ou page SSR complète (latence serveur sur chaque requête, pas de CDN cache). Server Islands offrent un mode hybride : la page principale reste statique servie depuis le CDN (rapide, économique), et seuls certains composants sont rendus côté serveur à la demande.
Cas d’usage typiques
- Header avec « Bonjour, [nom utilisateur] » personnalisé
- Bouton panier avec badge nombre d’articles
- Liste de produits récemment vus
- Statut commande dans page profil
- Notifications non lues
- A/B testing avec variant choisi côté serveur
- Contenu géo-localisé (Dakar vs Abidjan)
Étape 1 — Activer SSR hybride
// astro.config.mjs
import { defineConfig } from "astro/config";
import node from "@astrojs/node";
export default defineConfig({
output: "server", // ou "hybrid"
adapter: node({ mode: "standalone" }),
});
Pour Cloudflare Pages : adaptateur @astrojs/cloudflare. Pour Coolify avec Bun : adaptateur @astrojs/node + Dockerfile.
Étape 2 — Créer un Server Island
---
// src/components/UserGreeting.astro
const cookie = Astro.cookies.get("session");
let username = null;
if (cookie?.value) {
username = await getUserFromSession(cookie.value);
}
---
{username ? (
<p>Bonjour, {username} 👋</p>
) : (
<a href="/login">Se connecter</a>
)}
Étape 3 — Utiliser avec server:defer
---
// src/pages/index.astro (page essentiellement statique)
import Layout from "../layouts/Base.astro";
import UserGreeting from "../components/UserGreeting.astro";
import Skeleton from "../components/Skeleton.astro";
---
<Layout title="Accueil">
<h1>Bienvenue sur ITSkillsCenter</h1>
<!-- Cette section est différée : la page se charge en statique
puis l'island est récupérée via fetch et injectée -->
<UserGreeting server:defer>
<Skeleton slot="fallback" />
</UserGreeting>
<p>Reste de la page statique...</p>
</Layout>
Le visiteur voit immédiatement la page complète avec un Skeleton à la place du composant Server Island. Quelques millisecondes plus tard, le serveur retourne le rendu et Astro l’injecte. Pas de hydratation JS.
Étape 4 — Cache personnalisé
---
// Cache-Control sur les Server Islands
Astro.response.headers.set(
"Cache-Control",
"private, max-age=60"
);
---
Sur un Server Island contenant le panier, vous pouvez mettre du cache 30s (acceptable pour l’utilisateur). Sur des îles globales (top trending), du cache plus long (5 min).
Étape 5 — Encrypted props
Astro 5 chiffre automatiquement les props passés aux Server Islands. Critique pour la sécurité : l’utilisateur ne peut pas modifier les props pour exécuter avec d’autres paramètres.
// astro.config.mjs : clef de chiffrement (auto-générée si absente)
export default defineConfig({
output: "server",
experimental: {
serverIslands: true, // selon version
},
});
Étape 6 — Quand ne PAS utiliser Server Islands
- Si la totalité de la page change selon utilisateur → préférer SSR pleine page
- Si vous avez besoin d’interactivité côté client (formulaire, état) → Client Islands classiques (
client:load) - Si vos données changent en temps réel à chaque seconde → WebSocket et state client
Performance attendue
- HTML initial servi en ~50 ms depuis CDN edge (Cloudflare Lagos)
- Server Island fetched en parallèle, ~150-300 ms si serveur Helsinki
- Pas de blocage du rendu de la page principale
- Lighthouse Performance reste 95+ sur les pages avec 1-2 islands
Adaptation Afrique de l’Ouest
Server Islands sont parfaits pour les sites qui mêlent contenu marketing (statique, servi depuis edge Cloudflare proche d’un visiteur sénégalais) et fragments dynamiques (statut compte, panier, prix). Vous gardez la rapidité d’un site statique sans sacrifier la personnalisation.
Erreurs fréquentes
| Erreur | Cause | Solution |
|---|---|---|
| « server:defer not allowed in static pages » | output: ‘static’ | Passer en ‘server’ ou ‘hybrid’ |
| Island pas mise à jour | Cache CDN trop long | Cache-Control: private + max-age court |
| Slot fallback ne s’affiche pas | Mauvais slot name | slot= »fallback » exact |
| Encrypted props erreur | Clef différente entre déploiements | Persister la clef d’encryption en env var |
À lire ensuite
- guide pratique Astro 5
- Content Collections Astro 5
- Déployer Astro
- Documentation Server Islands : docs.astro.build
Etape 1 : verifier que votre projet tourne sur Astro 5.x
Les Server Islands sont disponibles a partir d’Astro 5.0 (sortie fin 2024) et stabilises avec les versions 5.1 et 5.2 publiees en 2025. Avant de plonger dans la mise en place, ouvrez un terminal a la racine du projet et controlez la version installee. Sur un VPS Hostinger ou un poste de developpement local a Dakar, Abidjan ou Lome, la commande est la meme.
npx astro --version
# Sortie attendue : 5.2.x ou superieur
Si la sortie affiche une version 4.x, faites la mise a niveau avec npm install astro@latest. Cette etape evite les erreurs cryptiques de compilation que beaucoup de developpeurs ouest-africains rencontrent quand ils suivent un tutoriel YouTube date.
Etape 2 : activer le mode hybride dans astro.config.mjs
Les Server Islands exigent un adaptateur de rendu serveur. Sans cela, le composant restera fige cote client. Ouvrez astro.config.mjs et ajoutez l’adaptateur Node ou Vercel selon votre cible de deploiement.
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'hybrid',
adapter: node({ mode: 'standalone' })
});
Apres redemarrage du serveur de developpement (npm run dev), Astro affiche dans le terminal la mention hybrid rendering enabled. C’est le signal que les ilots serveur peuvent maintenant etre injectes dans des pages statiques.
Etape 3 : isoler la section dynamique dans un composant .astro
Le principe d’un Server Island est simple : la majeure partie de la page reste statique (donc cacheable sur un CDN comme Cloudflare ou Bunny), et seule une zone precise est rendue a la demande sur le serveur. Pour un site marchand qui livre a Dakar avec paiement Wave ou Mixx by Yas, le contenu personnalise (panier, prix en FCFA selon le compte) sera l’ilot.
---
// src/components/PanierUtilisateur.astro
const userId = Astro.locals.user?.id;
const panier = userId ? await fetchPanier(userId) : null;
const totalFCFA = panier ? panier.total : 0;
---
<div class="panier">
<p>Votre panier : {totalFCFA.toLocaleString('fr-FR')} FCFA</p>
</div>
Le code s’execute uniquement cote serveur, ce qui protege les requetes base de donnees et evite d’exposer la logique au navigateur. Pour rappel, 1 EUR = 655,957 FCFA, donc un panier de 30 EUR s’affichera 19 679 FCFA.
Etape 4 : injecter l’ilot avec la directive server:defer
Dans la page parent (par exemple src/pages/index.astro), importez le composant et ajoutez l’attribut server:defer. C’est cette directive qui dit a Astro : genere la page principale en statique, mais reserve un slot pour ce composant qui sera rempli au moment de la requete.
---
import PanierUtilisateur from '../components/PanierUtilisateur.astro';
import Layout from '../layouts/Base.astro';
---
<Layout title="Boutique">
<h1>Nos produits</h1>
<!-- contenu statique -->
<PanierUtilisateur server:defer />
</Layout>
Au build, Astro genere un placeholder HTML et un fragment serveur. Le navigateur recoit la page rapidement, puis le fragment se rehydrate sans bloquer le First Contentful Paint. Sur une connexion 4G typique d’Abidjan ou Cotonou, le gain mesure depasse souvent 1,5 seconde.
Etape 5 : prevoir un fallback avec le slot fallback
Que se passe-t-il si l’ilot serveur tarde ou echoue ? Astro permet de definir un contenu de remplacement instantane via le slot nomme fallback. Cela evite l’effet de saut visuel et masque les erreurs reseau aux visiteurs.
<PanierUtilisateur server:defer>
<div slot="fallback" class="skeleton">
Chargement de votre panier...
</div>
</PanierUtilisateur>
En production, ce skeleton apparait pendant 200 a 600 ms le temps que le serveur reponde. Combine avec un cache Redis sur les sessions, vous pouvez descendre sous 100 ms meme depuis un VPS heberge a Marseille servant l’Afrique de l’Ouest.
Etape 6 : mettre en cache les fragments avec Cache-Control
Tous les ilots ne sont pas strictement personnels. Pour les sections qui changent rarement (top ventes du jour, taux de change EUR/FCFA), ajoutez un en-tete de cache dans le composant.
---
Astro.response.headers.set(
'Cache-Control',
'public, max-age=300, stale-while-revalidate=60'
);
---
Le fragment sera reutilise 5 minutes par votre CDN. Resultat : la charge sur le serveur d’origine baisse de 80 a 95 %, et la latence percue par les visiteurs senegalais ou maliens devient quasi instantanee. Verifiez avec curl -I que l’en-tete est bien renvoye.
Etape 7 : tester le rendu en mode production
Le mode dev d’Astro masque certaines erreurs liees au streaming. Construisez et lancez la version production pour valider le comportement reel.
npm run build
node ./dist/server/entry.mjs
# Sortie attendue : Server listening on http://localhost:4321
Ouvrez l’URL dans Chrome avec l’onglet Network ouvert. Vous devez voir une premiere reponse HTML rapide (souvent moins de 50 ko), puis une seconde requete pour le fragment server-island. Si les deux fusionnent, c’est que server:defer n’a pas ete pris en compte.
Etape 8 : deployer sur un VPS adapte au public ouest-africain
Pour un public concentre entre Dakar, Abidjan, Lome et Cotonou, privilegiez un VPS situe a Paris, Francfort ou Londres avec un CDN Cloudflare en frontal. Le plan VPS 1 de Hostinger (autour de 8 000 FCFA/mois) suffit pour 50 000 visites/mois si les ilots sont bien caches. Demarrez le serveur via PM2 pour la persistence.
npm install -g pm2
pm2 start ./dist/server/entry.mjs --name astro-app
pm2 save
# Sortie attendue : [PM2] App [astro-app] online
Verifiez avec pm2 status que l’application reste verte. PM2 redemarrera automatiquement le processus en cas de crash, ce qui couvre 99 % des incidents que rencontrent les sites Astro hybrides en production.
Etape 9 : mesurer et iterer avec Lighthouse
Le but final des Server Islands est mesurable : un score de performance superieur a 90 sur Lighthouse mobile, et un Largest Contentful Paint sous 2,5 secondes. Lancez l’audit depuis Chrome DevTools en simulant une connexion 4G et un CPU bride 4x.
Si le LCP reste eleve, verifiez que vos images servent en AVIF ou WebP, que la police est preloadee, et que le ilot ne contient pas de requete bloquante. Pour explorer plus loin, consultez notre tutoriel sur l’auto-hebergement reseau et notre guide de migration vers Forgejo pour heberger votre code source pres de votre infrastructure.
Etape 10 : tracer les erreurs serveur avec un logger structure
En production, un ilot qui echoue silencieusement est plus dangereux qu’un crash visible : le visiteur voit le fallback indefiniment et vous ne savez pas pourquoi. Ajoutez Pino (logger ultra-rapide) dans votre composant pour tracer chaque rendu.
---
import pino from 'pino';
const logger = pino({ level: 'info' });
try {
const panier = await fetchPanier(userId);
logger.info({ userId, total: panier.total }, 'panier_rendu');
} catch (err) {
logger.error({ err, userId }, 'panier_erreur');
}
---
Les logs JSON s’integrent ensuite a Grafana Loki ou a un simple tail -f sur le VPS. Vous reperez en quelques secondes si une requete base de donnees a depasse 800 ms ou si l’API Wave a renvoye un 503.
Etape 11 : securiser la communication entre ilots et API
Un Server Island execute du code privilegie. Il ne faut jamais exposer une cle API publique ou un secret de webhook dans la zone hydratee. Stockez vos cles dans .env et accedez-y uniquement cote serveur via import.meta.env.
# .env (jamais commite sur Git ou Forgejo)
WAVE_API_KEY=sk_live_xxxxxxxxxxxx
DB_URL=postgresql://user:pass@localhost:5432/boutique
Verifiez ensuite avec git status et cat .gitignore que le fichier .env est bien ignore. Une fuite de cle Wave ou Mixx by Yas peut couter cher a un commercant senegalais : changement immediat de credential et audit complet des transactions.
Etape 12 : enchainer plusieurs ilots independants sur la meme page
Rien n’empeche de combiner plusieurs Server Islands sur une page d’accueil : un ilot panier, un ilot recommandations, un ilot taux de change. Astro les rend en parallele, donc la page reste rapide tant que chaque ilot reste sous les 200 ms.
<PanierUtilisateur server:defer />
<Recommandations server:defer />
<TauxChange server:defer />
Mesurez avec l’onglet Network que les trois fragments arrivent quasi simultanement. Si l’un traine, isolez-le et optimisez sa requete (index SQL manquant, appel HTTP externe sans timeout). Le pattern Server Islands ne corrige pas un backend lent, il l’expose.
Etape 10 : tracer les erreurs serveur avec un logger structure
En production, un ilot qui echoue silencieusement est plus dangereux qu’un crash visible : le visiteur voit le fallback indefiniment et vous ne savez pas pourquoi. Ajoutez Pino (logger ultra-rapide) dans votre composant pour tracer chaque rendu.
import pino from 'pino';
const logger = pino({ level: 'info' });
try {
const panier = await fetchPanier(userId);
logger.info({ userId, total: panier.total }, 'panier_rendu');
} catch (err) {
logger.error({ err, userId }, 'panier_erreur');
}
Les logs JSON s’integrent a Grafana Loki ou a un simple tail -f sur le VPS. Vous reperez en quelques secondes si une requete a depasse 800 ms ou si l’API Wave a renvoye un 503. C’est ce niveau de visibilite qui fait la difference entre un site qui survit un Black Friday senegalais et un site qui s’effondre.
Etape 11 : securiser les secrets utilises par les ilots
Un Server Island execute du code privilegie. Ne jamais exposer une cle API ou un secret de webhook dans la zone hydratee cote client. Stockez les cles dans .env et accedez-y via import.meta.env uniquement dans le frontmatter du composant.
# .env (jamais commite sur Git ou Forgejo)
WAVE_API_KEY=sk_live_xxxxxxxxxxxx
DB_URL=postgresql://user:pass@localhost:5432/boutique
Verifiez ensuite avec cat .gitignore que le fichier .env est bien ignore. Une fuite de cle Wave ou Mixx by Yas oblige a une rotation immediate du credential et a un audit complet des transactions des dernieres 24h.
Etape 12 : enchainer plusieurs ilots independants
Rien n’empeche de combiner plusieurs Server Islands sur une page d’accueil : un ilot panier, un ilot recommandations, un ilot taux de change EUR/FCFA. Astro les rend en parallele, donc la page reste rapide tant que chaque ilot reste sous 200 ms.
<PanierUtilisateur server:defer />
<Recommandations server:defer />
<TauxChange server:defer />
Mesurez avec l’onglet Network que les trois fragments arrivent quasi simultanement. Si l’un traine, isolez-le et optimisez sa requete (index SQL manquant, appel HTTP externe sans timeout). Les Server Islands ne corrigent pas un backend lent, ils l’exposent.