vendredi 25 septembre 2026

À propos

Contact

Headless & API

Astro et les Islands pour un blog où seule la recherche reste interactive

Sur un blog éditorial où 95 % du contenu reste statique, une seule île Astro gère la recherche en direct contre l'API REST de WordPress, sans alourdir le reste du site.

Par Clément Hadrot • 12 juillet 2023 • 4 min de lecture • Aucun commentaire
Astro et les Islands pour un blog où seule la recherche reste interactive

Un blog culinaire à forte fréquentation, plus de six cents recettes publiées, a besoin d’exactement une fonctionnalité interactive : une recherche en direct qui filtre les recettes pendant que le visiteur tape, sans recharger la page. Tout le reste, du menu à l’affichage d’une recette complète, reste du contenu purement statique, sans le moindre besoin de JavaScript. C’est exactement le scénario pour lequel Astro et son architecture en îles (Islands) ont été pensés, et ce cas concret le démontre sur un projet réel livré ce printemps.

Cet article ne traite pas d’Astro et de son Content Layer, une fonctionnalité plus récente couverte dans un article ultérieur de ce blog. Il se concentre sur l’usage le plus simple et le plus caractéristique d’Astro : une île isolée dans un océan de pages statiques.

Le principe des Islands, appliqué à ce projet

Par défaut, une page .astro ne charge aucun JavaScript côté client, même si elle contient des composants React ou Vue importés dans son code. Seuls les composants explicitement marqués avec une directive client:* reçoivent leur propre bundle JavaScript, hydraté indépendamment du reste de la page. Sur ce blog, seule la barre de recherche a reçu cette directive, tout le reste du gabarit de page reste du HTML pur généré au build.

La page de listing, entièrement statique

---
// src/pages/recettes/index.astro
import { getCollection } from 'astro:content'
import BarreRecherche from '../../components/BarreRecherche.jsx'

const reponse = await fetch(
  'https://api.exemple.fr/wp-json/wp/v2/recette?per_page=100&_fields=id,slug,title,acf'
)
const recettes = await reponse.json()
---
<html lang="fr">
  <body>
    <h1>Toutes nos recettes</h1>

    <BarreRecherche client:load recettes={recettes} />

    <ul>
      {recettes.map((recette) => (
        <li>
          <a href={`/recettes/${recette.slug}`}>{recette.title.rendered}</a>
        </li>
      ))}
    </ul>
  </body>
</html>

La liste complète des recettes est générée directement dans le HTML statique, sans passer par l’île de recherche : celle-ci ne fait que filtrer visuellement cette même liste une fois hydratée côté client, elle n’est jamais responsable du rendu initial.

L'essentiel à retenir : Astro n'envoie aucun JavaScript par défaut sur une page statique ; Une seule directive client:load suffit à isoler l'interactivité ; Le poids du bundle JS reste minimal sur tout le reste du site

L’île de recherche, seule partie réellement interactive

// src/components/BarreRecherche.jsx
import { useState } from 'react'

export default function BarreRecherche({ recettes }) {
  const [filtre, setFiltre] = useState('')

  const recettesFiltrees = recettes.filter((r) =>
    r.title.rendered.toLowerCase().includes(filtre.toLowerCase())
  )

  return (
    <div>
      <input
        type="search"
        placeholder="Chercher une recette"
        value={filtre}
        onChange={(e) => setFiltre(e.target.value)}
      />
      {filtre && (
        <ul>
          {recettesFiltrees.map((r) => (
            <li key={r.id}>
              <a href={`/recettes/${r.slug}`}>{r.title.rendered}</a>
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}

La directive client:load indique à Astro d’hydrater ce composant dès le chargement de la page, un choix justifié ici puisque la barre de recherche doit être immédiatement utilisable. Sur une île moins prioritaire, client:visible aurait retardé l’hydratation jusqu’à ce que le composant entre dans le champ de vision du visiteur, pour économiser encore un peu de temps de chargement initial.

Le résultat mesuré

MétriqueAvant (thème classique)Après (Astro Islands)
JavaScript total chargé187 Ko14 Ko
Temps d’interactivité (TTI)2,4 s0,6 s
Score Lighthouse Performance7198

Pourquoi ce choix n’aurait pas fonctionné pour un site plus interactif

  • Un site avec un espace membre, un panier ou une messagerie interne aurait vu ses îles se multiplier au point de perdre l’intérêt de l’approche, chaque île ajoutant un point d’hydratation à coordonner.
  • Le partage d’état entre plusieurs îles distinctes reste plus artisanal qu’avec une application React unifiée, un compromis acceptable ici puisqu’une seule île existe sur tout le site.
  • Astro reste avant tout pensé pour du contenu majoritairement statique : un site fortement applicatif gagnerait probablement plus à choisir un framework pensé pour ça dès le départ.

Le bon réflexe avec Astro n’est pas de se demander « comment rendre ma page interactive », mais « quelle est la plus petite partie de ma page qui a réellement besoin de l’être ».

En résumé

Sur ce blog culinaire, une seule île Astro suffit à couvrir l’unique besoin d’interactivité réel du site, laissant tout le reste du contenu strictement statique et donc extrêmement rapide à charger. Le gain de performance mesuré n’a rien d’anecdotique : il illustre exactement la promesse d’Astro, livrer du JavaScript uniquement là où il apporte une vraie valeur, jamais par défaut sur l’ensemble d’un site.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi