Headless Drupal : pourquoi et comment découpler votre CMS

Découvrez le Drupal headless : avantages du découplage, cas d'usage pertinents, et tutoriel JSON:API pour créer votre première API.

Le Drupal headless représente une évolution majeure dans la façon de concevoir des projets web. En séparant le back-end du front-end, cette architecture ouvre des possibilités que le CMS traditionnel ne permet pas. Mais est-ce adapté à votre projet ? Je vous propose un tour d'horizon complet basé sur mes expériences terrain.

Qu'est-ce que le Drupal headless exactement ?

Dans une architecture Drupal classique (dite "couplée"), le CMS gère à la fois le contenu et son affichage. Les thèmes Twig transforment les données en HTML envoyé au navigateur.

Avec l'approche headless (ou "découplée"), Drupal se concentre uniquement sur la gestion du contenu. Il expose les données via une API, et un front-end séparé (React, Vue, Next.js, application mobile...) se charge de l'affichage.

Les trois niveaux de découplage

Il existe en réalité un spectre de solutions :

  • Couplé traditionnel : Drupal gère tout, du contenu au rendu HTML
  • Progressivement découplé : Drupal génère le HTML de base, JavaScript enrichit certaines zones
  • Totalement découplé (headless) : Drupal = API pure, front-end totalement indépendant

Chaque approche a ses mérites. Le choix dépend de vos contraintes et objectifs.

Pourquoi choisir une architecture headless ?

Les avantages concrets

Flexibilité du front-end

Vous n'êtes plus limité aux capacités de Twig. Utilisez React, Vue, Svelte, ou n'importe quel framework JavaScript moderne. Vos développeurs front-end travaillent avec les outils qu'ils maîtrisent.

Multi-canal natif

Une seule source de contenu alimente plusieurs interfaces :

  • Site web desktop et mobile
  • Application native iOS/Android
  • Bornes interactives
  • Affichage digital signage
  • Assistants vocaux

C'est particulièrement pertinent pour les entreprises qui doivent diffuser du contenu sur plusieurs canaux.

Performances optimisées

Les frameworks JavaScript modernes excellent en performance. Avec le rendu statique (SSG) ou le rendu côté serveur (SSR), vous obtenez des temps de chargement exceptionnels. Les scores Core Web Vitals s'en trouvent naturellement améliorés.

Scalabilité indépendante

Le back-end Drupal et le front-end peuvent évoluer séparément. Besoin de plus de puissance pour l'API ? Vous ne touchez pas au front. Le front doit supporter un pic de trafic ? Le CDN s'en charge sans solliciter Drupal.

Sécurité renforcée

Le front-end peut être un site statique hébergé sur un CDN. Drupal, n'étant pas exposé directement aux visiteurs, présente une surface d'attaque réduite.

Les contreparties à considérer

Soyons honnêtes, le headless n'est pas gratuit :

  • Complexité accrue : deux projets à maintenir au lieu d'un
  • Compétences requises : maîtrise de JavaScript moderne en plus de Drupal
  • Fonctionnalités natives perdues : prévisualisation, blocs contextuels, certains modules contrib
  • Coût de développement initial : plus élevé qu'un site Drupal classique

Si votre projet est un site vitrine simple, le headless est probablement overkill. Pour des projets complexes ou multi-canaux, l'investissement se justifie.

Cas d'usage pertinents pour le headless

Quand le headless s'impose

Applications web interactives

Tableaux de bord, configurateurs produits, outils interactifs... Si votre front-end nécessite une forte interactivité, React ou Vue seront plus adaptés que Twig.

Écosystème multi-applications

Vous avez un site web, une app mobile, et bientôt une app TV ? Le headless évite de dupliquer la gestion de contenu.

Équipes front-end spécialisées

Vos développeurs front sont experts React mais ne connaissent pas Drupal ? Le découplage leur permet de travailler dans leur environnement.

Performance critique

Les sites e-commerce à fort trafic ou les médias en ligne bénéficient du rendu statique et de la mise en cache agressive que permet le headless.

Quand rester en couplé

  • Sites vitrines ou institutionnels classiques
  • Budget limité
  • Équipe réduite sans expertise JavaScript
  • Besoin fort d'édition en contexte (Layout Builder, Paragraphs)
  • Délais serrés

Si vous hésitez, parlons de votre projet. Un audit rapide permet souvent de trancher.

JSON:API : l'API native de Drupal

Depuis Drupal 8, le module JSON:API fait partie du core. Il expose automatiquement toutes vos entités (nodes, taxonomies, utilisateurs, médias...) via une API REST conforme à la spécification JSON:API.

Activer JSON:API

drush en jsonapi

C'est tout. Vos contenus sont immédiatement accessibles via l'API.

Structure des endpoints

Les URLs suivent une convention prévisible :

/jsonapi/node/article          → Liste des articles
/jsonapi/node/article/{uuid}   → Un article spécifique
/jsonapi/taxonomy_term/tags    → Liste des tags
/jsonapi/media/image           → Liste des médias images

Exemple de requête

Récupérons les 10 derniers articles publiés avec leurs auteurs :

curl "https://monsite.com/jsonapi/node/article?include=uid&sort=-created&page[limit]=10"

La réponse JSON contient les articles avec leurs relations :

{
  "data": [
    {
      "type": "node--article",
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "attributes": {
        "title": "Mon article",
        "body": {
          "value": "<p>Contenu...</p>",
          "format": "full_html"
        },
        "created": "2025-02-15T10:30:00+00:00"
      },
      "relationships": {
        "uid": {
          "data": {
            "type": "user--user",
            "id": "..."
          }
        }
      }
    }
  ],
  "included": [
    {
      "type": "user--user",
      "id": "...",
      "attributes": {
        "name": "admin"
      }
    }
  ]
}

Filtrer les résultats

JSON:API supporte des filtres puissants :

# Articles d'une catégorie spécifique
/jsonapi/node/article?filter[field_category.id]=UUID_CATEGORIE

# Articles contenant un mot dans le titre
/jsonapi/node/article?filter[title][operator]=CONTAINS&filter[title][value]=drupal

# Articles publiés après une date
/jsonapi/node/article?filter[created][operator]=%3E&filter[created][value]=2025-01-01

Sécuriser l'API

Par défaut, JSON:API respecte les permissions Drupal. Un visiteur anonyme ne voit que les contenus publiés accessibles au rôle anonyme.

Pour aller plus loin :

  • Authentification OAuth2 : module Simple OAuth pour les tokens
  • Limitation de débit : module Rate Limiter
  • CORS : configuration dans services.yml
# services.yml
cors.config:
  enabled: true
  allowedOrigins: ['https://mon-front.com']
  allowedMethods: ['GET', 'POST', 'PATCH', 'DELETE']
  allowedHeaders: ['Content-Type', 'Authorization']

Intégrer Drupal headless avec Next.js

Next.js est un choix populaire pour le front-end headless. Voici comment démarrer.

Configuration du projet Next.js

npx create-next-app mon-front-drupal
cd mon-front-drupal

Récupérer les données Drupal

Créez un fichier pour les appels API :

// lib/drupal.js
const DRUPAL_URL = process.env.NEXT_PUBLIC_DRUPAL_URL;

export async function getArticles() {
  const response = await fetch(
    `${DRUPAL_URL}/jsonapi/node/article?include=field_image&sort=-created`
  );

  if (!response.ok) {
    throw new Error('Erreur lors de la récupération des articles');
  }

  return response.json();
}

export async function getArticle(slug) {
  const response = await fetch(
    `${DRUPAL_URL}/jsonapi/node/article?filter[field_slug]=${slug}&include=field_image,uid`
  );

  const data = await response.json();
  return data.data[0] || null;
}

Afficher les articles

// app/blog/page.js
import { getArticles } from '@/lib/drupal';

export default async function BlogPage() {
  const { data: articles } = await getArticles();

  return (
    <main>
      <h1>Blog</h1>
      <ul>
        {articles.map((article) => (
          <li key={article.id}>
            <a href={`/blog/${article.attributes.field_slug}`}>
              {article.attributes.title}
            </a>
          </li>
        ))}
      </ul>
    </main>
  );
}

Gestion des images

Les images Drupal nécessitent un traitement particulier :

// lib/drupal.js
export function getImageUrl(included, imageRelationship) {
  if (!imageRelationship?.data) return null;

  const imageData = included.find(
    (item) => item.id === imageRelationship.data.id
  );

  return imageData?.attributes?.uri?.url
    ? `${DRUPAL_URL}${imageData.attributes.uri.url}`
    : null;
}

Alternatives à JSON:API

GraphQL avec le module GraphQL

Si vous préférez GraphQL, le module GraphQL offre une alternative puissante :

query {
  articles(first: 10) {
    nodes {
      title
      body {
        processed
      }
      author {
        name
      }
    }
  }
}

Avantages de GraphQL :

  • Requêtes sur mesure (pas de sur-fetching)
  • Typage fort
  • Introspection du schéma

Inconvénients :

  • Configuration plus complexe
  • Module contrib (pas dans le core)

REST avec Views

Le module REST UI permet d'exposer des vues Drupal en JSON. Pratique pour des endpoints très spécifiques sans coder.

Mes recommandations pour un projet headless réussi

Après plusieurs projets headless, voici mes conseils :

Côté Drupal

  1. Structurez bien vos contenus : pensez API dès la conception des types de contenu
  2. Utilisez les UUID : plus stables que les nids pour les références
  3. Documentez votre API : le module OpenAPI génère une documentation Swagger
  4. Prévoyez l'authentification : même pour un site public, sécurisez les endpoints sensibles

Côté front-end

  1. Cachez agressivement : utilisez ISR (Incremental Static Regeneration) avec Next.js
  2. Gérez les erreurs : l'API peut être lente ou indisponible
  3. Optimisez les images : utilisez next/image ou équivalent
  4. Prévoyez le SEO : SSR ou SSG pour l'indexation

Organisation projet

  1. Monorepo ou repos séparés : à définir selon votre équipe
  2. Environnements alignés : dev, staging, prod pour les deux projets
  3. CI/CD adaptée : déploiements coordonnés si nécessaire

Ressources pour aller plus loin

Le headless est-il fait pour vous ?

L'architecture headless Drupal offre une flexibilité remarquable, mais elle n'est pas universelle. Le choix dépend de vos contraintes techniques, de votre équipe, et de vos objectifs à moyen terme.

Si vous hésitez entre une approche couplée et découplée, ou si vous souhaitez un accompagnement pour mettre en place une architecture headless, contactez-moi. Je peux vous aider à évaluer la meilleure stratégie pour votre projet.