Un client m'a appelé début 2023 — un éditeur de médias gérant environ 14 000 articles sur WordPress, un thème assemblé au fil de quatre développeurs sur six ans, et un score Core Web Vitals qui était franchement embarrassant. Son LCP affichait 7,2 secondes sur mobile. Ils avaient essayé WP Rocket, ils avaient essayé un CDN, ils avaient même supprimé la moitié de leurs plugins. Toujours lent. Le problème n'était pas WordPress lui-même. C'était que chaque rendu de page passait par PHP, un thème alourdi, et une chaîne de requêtes de base de données qu'on n'avait pas examinée depuis 2018.
C'est le moment où je me suis vraiment engagé dans une configuration headless avec Astro comme frontend. Pas parce que c'est à la mode — parce que pour un site contenant des milliers d'articles avec du contenu éditorial dense, c'était la seule architecture qui avait du sens.Astro as the frontend. Not because it's fashionable — because for a site pushing thousands of posts with heavy editorial content, it was the only architecture that made sense.
Voici exactement comment je l'ai configuré. Les compromis, la vraie configuration, les points qui m'ont posé problème.
---
Pourquoi Astro et Pas Next.js
Je reçois souvent cette question. Next.js est la réponse évidente si vous avez déjà une équipe fortement orientée React ou si vous avez besoin d'interactivité côté client complexe. Mais pour les sites lourds en contenu ? Astro gagne, et ce n'est pas particulièrement serré.
Astro n'expédie zéro JavaScript par défaut. Pour un blog, un site d'actualités ou un portail de documentation, c'est le bon défaut. Vous activez JavaScript là où vous en avez besoin, plutôt que de désactiver un bundle React de 200 kb que vous ne voulez généralement pas. La documentation d'Astro sur l'hydratation partielle — ils appellent ça l'architecture Islands — l'explique mieux que je ne pourrais le faire en une phrase, mais en résumé : seules les parties interactives reçoivent du JS. Le corps de l'article, l'en-tête, la barre latérale ? HTML statique.zero JavaScript by default. For a blog, a news site, or a documentation portal, that's the correct default. You opt into JavaScript where you need it, rather than opting out of a 200kb React bundle you mostly don't want. The Astro docs on partial hydration — they call it the Islands architecture — explain it better than I can in a sentence, but the short version is: only the interactive bits get JS. The article body, the header, the sidebar? Static HTML.
J'ai construit un site de contenu juridique fin 2022 avec Next.js et WordPress. Assez rapide, mais le client demandait constamment pourquoi son score Lighthouse était 74 sur mobile alors que « ça devrait être rapide maintenant ». Surcharge d'hydratation. Avec Astro, ce même type de site atteint maintenant régulièrement 95–98. Pas de vantardise — c'est juste ce que l'architecture vous donne gratuitement.
Ce qu'Astro n'est pas bon à faire
C'est important d'être honnête. Si votre site a besoin de personnalisation en temps réel, d'un panier d'achat lourd, ou de quelque chose qui dépend vraiment de l'état côté client sur plusieurs composants, Astro commence à sembler maladroit. Ce n'est pas une application React. Le motif Islands est puissant, mais c'est un modèle mental différent de la construction d'SPA. J'ai essayé de forcer un tableau de bord client dans un projet Astro mi-2023 et j'ai fini par revenir à Next.js en deux semaines. Sachez ce que vous construisez.
---
Configurer WordPress comme CMS découplé
WordPress est véritablement un bon backend découplé. L'API REST WP est livrée dans le cœur, elle est bien documentée, et votre équipe éditoriale n'a rien de nouveau à apprendre. Ce dernier point compte bien plus que les développeurs ne l'admettent généralement.WP REST API ships in core, it's well-documented, and your editorial team doesn't have to learn anything new. That last point matters more than developers usually admit.
Voici la configuration que j'utilise :
- Installez WordPress sur un sous-domaine — j'utilise cms.yourdomain.com ou api.yourdomain.com. Gardez-le derrière l'authentification basique ou du moins limitez le trafic public direct. Le frontend est yourdomain.com. Deux déploiements distincts. — I use
cms.yourdomain.comorapi.yourdomain.com. Keep it behind basic auth or at minimum restrict direct public traffic. The frontend isyourdomain.com. Two separate deployments. - Installez le [plugin WPGraphQL](https://www.wpgraphql.com/) — je préfère GraphQL à REST pour les sites de contenu parce que vous pouvez co-localiser vos requêtes avec vos composants et récupérer exactement les champs dont vous avez besoin. Pas de sur-récupération. L'API REST fonctionne bien, mais une fois que vous avez 15+ champs personnalisés par type de publication, l'approche GraphQL est nettement plus propre. — I prefer GraphQL over REST for content sites because you can co-locate your queries with your components and fetch exactly the fields you need. No over-fetching. The REST API is fine, but once you've got 15+ custom fields per post type, the GraphQL approach is noticeably cleaner.
- Installez Advanced Custom Fields (ACF) et l'extension WPGraphQL for ACF. Cette combinaison est ce qui rend WordPress véritablement flexible en tant que modèle de contenu headless — vous pouvez définir des données structurées par type de publication, les exposer via GraphQL, et Astro les consomme correctement. and the WPGraphQL for ACF extension. This combo is what makes WordPress genuinely flexible as a headless content model — you can define structured data per post type, expose it through GraphQL, and Astro consumes it cleanly.
- Désactivez les commentaires, les emojis et le XML-RPC par défaut si vous ne l'avez pas déjà fait. Ceux-ci ajoutent une surcharge et une surface d'attaque dont vous n'avez pas besoin. if you haven't already. These add overhead and attack surface you don't need.
- Définissez les permaliens à quelque chose de sensé avant de commencer à construire. Les changer en milieu de projet une fois que vos routes Astro sont déjà en place, c'est vraiment pénible. to something sensible before you start building. Changing them mid-project when your Astro routes are already set is a genuine pain.
Une chose qui piège les gens : CORS. Par défaut, WordPress ne laissera pas votre serveur de développement Astro (fonctionnant sur localhost:4321) faire des requêtes vers votre installation WP. Mettez ceci dans le functions.php de votre thème ou un petit plugin utilitaire pendant le développement :localhost:4321) make requests to your WP install. Drop this into your theme's functions.php or a small utility plugin during development:
`` add_action('init', function() { header("Access-Control-Allow-Origin: *"); }); `` add_action('init', function() { header("Access-Control-Allow-Origin: *"); }); ``
Resserrez cela sur des origines spécifiques en production. Évidemment.
---
La Structure du Projet Astro
Je la garde opinée et cohérente d'un projet à l'autre. Après une douzaine ou so de constructions headless, c'est ce qui fonctionne :
`` src/ components/ layouts/ pages/ index.astro blog/ [slug].astro lib/ wpgraphql.ts ← toute la logique de requête WP vit ici styles/ `` src/ components/ layouts/ pages/ index.astro blog/ [slug].astro lib/ wpgraphql.ts ← all WP query logic lives here styles/ ``
Le fichier lib/wpgraphql.ts est l'endroit où je centralise chaque fetch GraphQL. Pas d'appels fetch en ligne éparpillés dans les fichiers de page. Chaque requête est une fonction async nommée et exportée. Déboguer cela sur 14 000 articles quand quelque chose casse à 2h du matin — tu te remercieras plus tard.lib/wpgraphql.ts file is where I centralise every GraphQL fetch. No inline fetch calls scattered across page files. Every query is a named, exported async function. Debugging this across 14,000 posts when something breaks at 2am — you'll thank yourself later.
Récupérer les articles au moment de la construction
getStaticPaths d'Astro est ton pain et beurre ici. Pour un blog avec des milliers d'articles :getStaticPaths is your bread and butter here. For a blog with thousands of posts:
`` export async function getStaticPaths() { const posts = await getAllPostSlugs(); // appelle WPGraphQL return posts.map(post => ({ params: { slug: post.slug }, })); } `` export async function getStaticPaths() { const posts = await getAllPostSlugs(); // calls WPGraphQL return posts.map(post => ({ params: { slug: post.slug }, })); } ``
getAllPostSlugs pagine dans WPGraphQL en utilisant des curseurs after — la couche GraphQL de WordPress retourne 100 articles par requête par défaut, donc pour 14 000 articles tu fais 140 requêtes au moment de la construction. Ça semble effrayant. En pratique, sur un serveur décent, la construction complète s'exécute en environ 4–5 minutes. Parfaitement acceptable pour un site qui se reconstruit quelques fois par jour. paginates through WPGraphQL using after cursors — WordPress's GraphQL layer returns 100 posts per request by default, so for 14,000 posts you're making 140 requests at build time. That sounds scary. In practice, on a decent server, the full build runs in about 4–5 minutes. Perfectly acceptable for a site that rebuilds a few times per day.
---
Gérer les images sans perdre la tête
C'est le bit dont personne ne parle assez. WordPress stocke les URLs d'images pointant vers ton sous-domaine CMS. Quand Astro construit statiquement, ces images vivent toujours sur cms.yourdomain.com — ce qui signifie que les navigateurs de tes visiteurs récupèrent les images de ton serveur WordPress, contournant potentiellement ton CDN.cms.yourdomain.com — which means your visitors' browsers are fetching images from your WordPress server, potentially bypassing your CDN.
Quelques façons de gérer cela :
- Cloudflare devant les deux domaines. L'option la plus simple. Proxy à travers Cloudflare yourdomain.com et cms.yourdomain.com, configurez un cache agressif sur /wp-content/uploads/*, et c'est bon. Simplest option. Proxy both
yourdomain.comandcms.yourdomain.comthrough Cloudflare, configure aggressive caching on/wp-content/uploads/*, and you're mostly fine. - Utilisez un plugin de délocalisation média. J'aime bien WP Offload Media — il déplace les uploads vers S3 (ou un stockage compatible) et réécrit les URLs automatiquement. C'est l'approche que j'utilise pour n'importe quel site attendant un trafic sérieux. Votre serveur WordPress arrête complètement de servir les images. I like WP Offload Media — it moves uploads to S3 (or compatible storage) and rewrites URLs automatically. This is the approach I use for any site expecting serious traffic. Your WordPress server stops serving images entirely.
- Le composant Image d'Astro. Pour les images que vous contrôlez au moment du build (images à la une récupérées via GraphQL), vous pouvez passer l'URL distante au composant <Image> d'Astro et il les optimisera, les redimensionnera et les servira à partir de votre sortie de build. Ça fonctionne très bien. Ça ne fonctionne pas pour les images intégrées dans le corps HTML du post — ça demande un traitement différent. For images you control at build time (featured images pulled via GraphQL), you can pass the remote URL into Astro's
<Image>component and it'll optimise, resize, and serve them from your build output. Works brilliantly. Does not work for images embedded in post body HTML — that requires a different pass.
Seahawk avait un client spécialisé en contenu de voyage l'année dernière — environ 8 000 posts, extrêmement lourds en images, moyenne de 12 images par article. Leur serveur WordPress était martelé uniquement par les requêtes d'images même avec le setup headless. Passer à S3 + CloudFront a réduit leur bande passante d'origine de 94 %. Vraiment transformateur pour leur facture d'hébergement.
---
Builds Incrémentaux et le Problème du Rebuild
Voici un vrai problème avec la génération statique à l'échelle : votre éditeur publie une correction de post à 15h et doit attendre 5 minutes pour un rebuild complet. Ce n'est pas acceptable dans une salle de rédaction.
Quelques approches que j'ai utilisées :
Option 1 : Netlify ou Vercel avec ISR à la demande. Astro supporte le rendu côté serveur avec des adaptateurs — vous pouvez lancer Astro en mode hybride où la plupart des pages sont statiques mais certaines routes sont rendues à la demande. Pour un site d'actualités, je pré-rendrai souvent statiquement les 30 derniers jours de posts (trafic élevé, besoin de vitesse) et je mettrai les pages d'archives plus anciennes en rendu serveur à la demande. Le meilleur des deux mondes. Astro supports server-side rendering with adapters — you can run Astro in hybrid mode where most pages are static but specific routes are rendered on-demand. For a news site, I'll often statically pre-render the last 30 days of posts (high traffic, needs speed) and set older archive pages to server-render on demand. Best of both worlds.
Option 2 : Builds partiels déclenchés par webhook. WordPress déclenche un webhook à la sauvegarde du post (facile avec le plugin WP Webhooks). Ce webhook frappe un hook de déploiement Netlify ou Vercel. Le build s'exécute, il ne récupère que ce qui a changé. Ce n'est pas vraiment partiel — Astro reconstruit quand même tout — mais si vous gardez votre build rapide, 4 minutes c'est gérable. WordPress fires a webhook on post save (easy with the WP Webhooks plugin). That webhook hits a Netlify or Vercel deploy hook. The build runs, it fetches only what's changed. It's not truly partial — Astro still rebuilds everything — but if you keep your build fast, 4 minutes is workable.
Option 3 : utiliser simplement SSR pour tout. Déployer Astro avec l'adaptateur Node sur un VPS (j'utilise Hetzner pour cela — pas cher, rapide, fiable). Chaque page se génère à la demande, vous mettez en cache de manière agressive au niveau d'Nginx ou Cloudflare, et vous avez des mises à jour de contenu instantanées. C'est ce que je ferais pour une vraie opération d'édition avec plus de 50 000 articles. Deploy Astro with the Node adapter to a VPS (I use Hetzner for this — cheap, fast, reliable). Every page renders on request, you cache aggressively at the Nginx or Cloudflare level, and you have instant post updates. This is what I'd do for a proper publishing operation over 50,000 posts.
Pour être honnête ? La plupart des sites n'ont pas besoin de la complexité de l'Option 1 ou 3. Une reconstruction de 4 minutes déclenchée par un webhook, c'est bon pour 90 % des sites de contenu.
---
Performance : ce que vous obtenez réellement
Sur le projet d'édition de l'introduction — voici ce qui s'est passé après la migration vers Astro :
- LCP est passé de 7.2s à 1.1s sur mobile (testé avec WebPageTest depuis un nœud à Londres)1.1s on mobile (tested with WebPageTest from a London node)
- Total Blocking Time est passé de ~800ms à 0ms (zéro JS par défaut, souvenez-vous)0ms (zero JS by default, remember)
- Leur rapport Core Web Vitals de Google Search Console est passé de 3 % d'URLs « Bon » à 91 % « Bon » en six semaines suivant le déploiement91% "Good" within six weeks of deployment
- Les coûts d'hébergement ont baissé parce que leur serveur WordPress ne servait plus les pages, seulement les réponses API
Rien de magique là-dedans. C'est juste ce qui se passe quand on retire le rendu PHP du chemin critique et qu'on arrête de livrer un bundle JavaScript de theme de 400kb à chaque lecteur.
---
Les points qui vont vous piéger
Sans détour — les choses que j'ai dû déboguer sur des vrais projets :
- Les aperçus de brouillon. C'est vraiment pénible dans une architecture headless. L'aperçu natif de WordPress repose sur le rendu front-end. Vous avez besoin de construire un endpoint d'aperçu personnalisé dans Astro qui accepte un nonce d'aperçu WordPress et récupère le brouillon via WPGraphQL. Pas compliqué, mais ça prend une journée pour le faire correctement. This is genuinely annoying in a headless setup. WordPress's native preview relies on front-end rendering. You need to build a custom preview endpoint in Astro that accepts a WordPress preview nonce and fetches the draft via WPGraphQL. Not hard, but it takes a day to do properly.
- Les redirections. Si l'ancien site avait des centaines de redirections dans .htaccess, elles vivent maintenant sur le serveur WordPress. Vous devez soit les reproduire dans la config d'Astro, soit garder WordPress accessible et faire un proxy sur des chemins spécifiques. J'ai fait les deux. Reproduire dans Astro est plus propre à long terme. If the old site had hundreds of redirects in
.htaccess, those live on the WordPress server now. You need to either replicate them in Astro's config, or keep WordPress accessible and proxy specific paths. I've done both. Replicating in Astro is cleaner long-term. - La recherche. La recherche intégrée de WordPress est inutile dans une architecture headless. J'utilise Algolia avec le plugin WP Search with Algolia. Indexez vos articles dans WP, interrogez Algolia depuis un composant Astro Island. Ça marche bien. WordPress's built-in search is useless in a headless setup. I use Algolia with the WP Search with Algolia plugin. Index your posts in WP, query Algolia from an Astro Island component. Works well.
- Les menus et la navigation. Les menus WordPress sont bizarrement fastidieux à exposer via WPGraphQL. La route wpgraphql-acf finit souvent par être plus propre — modelez simplement votre nav comme un répéteur ACF et c'est bon. WordPress menus are weirdly fiddly to expose through WPGraphQL. The
wpgraphql-acfroute often ends up being cleaner — just model your nav as an ACF repeater and call it done.
---
FAQ
Ai-je besoin de WPGraphQL ou puis-je simplement utiliser l'API REST ?
Vous pouvez tout à fait utiliser la REST API — elle est intégrée au cœur de WordPress et ne nécessite aucun plugin supplémentaire. Pour les sites simples avec des types de contenus standard et un minimum de champs personnalisés, c'est correct. GraphQL trouve sa place quand vous avez des modèles de contenus complexes avec beaucoup de champs personnalisés par type. Pouvoir récupérer exactement les champs dont vous avez besoin en une seule requête, sans vous battre avec les paramètres _embed et les appels REST imbriqués, vous fait gagner du temps à chaque requête que vous écrivez. À vous de voir. Je trouve juste GraphQL plus propre passé un certain seuil de complexité._embed parameters and nested REST calls, saves time on every query you write. Up to you. I just find GraphQL cleaner past a certain complexity threshold.
Comment gérer l'authentification WordPress pour le contenu réservé aux membres ?
L'authentification JWT est l'approche standard. Installez le plugin JWT Authentication for WP REST API, émettez des tokens à la connexion, passez-les dans les en-têtes de votre requête GraphQL. Du côté d'Astro, vous géreriez cela avec une route SSR (pas statique) pour que le contenu spécifique à l'utilisateur soit récupéré côté serveur à chaque requête. Ne tentez pas de faire cela statiquement — c'est la route vers la folie.JWT Authentication for WP REST API plugin, issue tokens on login, pass them in your GraphQL request headers. On the Astro side, you'd handle this with an SSR route (not static) so the user-specific content is fetched server-side per request. Don't try to do this statically — that way lies madness.
N'est-ce pas exagéré pour un petit blog ?
Oui, probablement. Si vous avez moins de 500 articles et un seul éditeur, la charge de maintenir une architecture headless n'en vaut pas la peine. Utilisez simplement un bon thème WordPress, optimisez vos images, et passez à autre chose. Cette architecture s'amortit quand vous avez du volume, de la complexité éditoriale, ou des niveaux de trafic où la performance impacte réellement vos revenus.
À quoi ressemble la configuration d'hébergement en production ?
WordPress (CMS uniquement) sur un petit VPS ou un hôte WordPress managé — j'utilise Kinsta ou Cloudways. Frontend Astro sur Vercel, Netlify, ou un VPS Hetzner avec Nginx selon le projet. Cloudflare devant tout. Le coût mensuel total pour un site de contenu de taille moyenne est généralement entre 60 et 120 £, ce qui est souvent moins que ce que les clients payaient pour un hôte WordPress tout-en-un qui peinait sous la charge.less than what clients were paying for an all-in-one WordPress host that was struggling under the load.
---
Le résumé honnête est celui-ci : WordPress headless avec Astro est l'une des meilleures choses qui soit arrivée aux sites de contenu depuis un moment. Non pas parce que c'est nouveau, mais parce que l'écosystème a enfin rattrapé l'idée. WPGraphQL est stable, le système de build d'Astro est rapide, et les gains de performance sont réels et mesurables.
Mettez en place l'architecture correctement dès le départ — surtout votre stratégie d'images et votre approche de reconstruction — et vous passerez beaucoup moins de temps à éteindre les incendies plus tard. C'est vraiment tout.
