Essayez sans attendre l'hébergement proposé par WordPress
-15% sur le premier mois avec le code 2025PRESS15AFF

Essayer maintenant

WordPress et les Web Components : Intégration native sans framework

Alors que WordPress pousse de plus en plus vers React et les frameworks JavaScript, il existe une alternative native souvent négligée : les Web Components. Ces technologies du navigateur permettent de créer des composants encapsulés sans aucune dépendance externe, parfaits pour enrichir vos thèmes et plugins WordPress. Découvrons comment s’affranchir du build et exploiter la puissance native du navigateur pour des développements plus simples et performants.

Les Web Components : Custom Elements, Shadow DOM et HTML Templates

Bon, avant de voir comment intégrer tout ça dans WordPress, on va d’abord comprendre ce que sont vraiment les Web Components. Et croyez-moi, c’est beaucoup plus simple qu’on pourrait le penser !

Les Web Components, c’est en fait trois technologies natives du navigateur qui fonctionnent ensemble : les Custom Elements, le Shadow DOM et les HTML Templates. Pensez à ça comme une boîte à outils complète pour créer vos propres éléments HTML réutilisables.

Custom Elements : vos propres balises HTML

Les Custom Elements, c’est la possibilité de créer ses propres balises HTML. Un peu comme si vous pouviez inventer <mon-bouton> ou <carte-produit> et que le navigateur comprenne parfaitement ce que c’est.

Voici comment ça marche :

class MonBouton extends HTMLElement {
  constructor() {
    super();
    this.innerHTML = `
      <button style="background: #007cba; color: white; padding: 10px;">
        ${this.textContent}
      </button>
    `;
  }
}

customElements.define('mon-bouton', MonBouton);

Et dans votre HTML :

<mon-bouton>Cliquez ici</mon-bouton>

Magique, non ? Contrairement à React ou Vue où vous devez compiler votre code, ici c’est du JavaScript vanilla que le navigateur comprend directement.

Shadow DOM : l’encapsulation parfaite

Alors là, on touche au truc vraiment puissant. Le Shadow DOM, c’est comme créer une bulle autour de votre composant. Rien ne peut entrer, rien ne peut sortir (au niveau CSS et JavaScript).

Pensez au lecteur vidéo de votre navigateur : vous voyez bien les boutons play/pause, mais vous ne pouvez pas les styler avec votre CSS. C’est exactement le principe !

class CarteUtilisateur extends HTMLElement {
  constructor() {
    super();
    
    // Création du Shadow DOM
    const shadow = this.attachShadow({mode: 'open'});
    
    shadow.innerHTML = `
      <style>
        .carte {
          border: 1px solid #ddd;
          padding: 16px;
          border-radius: 8px;
          background: white;
        }
        .nom {
          font-weight: bold;
          color: #007cba;
        }
      </style>
      <div class="carte">
        <div class="nom">${this.getAttribute('nom')}</div>
        <div class="email">${this.getAttribute('email')}</div>
      </div>
    `;
  }
}

customElements.define('carte-utilisateur', CarteUtilisateur);

Le CSS défini dans le Shadow DOM ne peut pas être écrasé par vos styles WordPress. C’est l’encapsulation totale !

HTML Templates : la structure réutilisable

Les templates, c’est votre moule à gâteau. Vous définissez une structure une fois, et vous la réutilisez partout où vous en avez besoin.

<template id="produit-template">
  <style>
    .produit {
      display: flex;
      gap: 16px;
      padding: 20px;
      border: 1px solid #eee;
    }
    .image {
      width: 100px;
      height: 100px;
      object-fit: cover;
    }
  </style>
  <div class="produit">
    <img class="image" alt="">
    <div class="infos">
      <h3><slot name="nom"></slot></h3>
      <p><slot name="prix"></slot></p>
      <slot name="description"></slot>
    </div>
  </div>
</template>

<script>
class CarteProduit extends HTMLElement {
  constructor() {
    super();
    
    const template = document.getElementById('produit-template');
    const shadow = this.attachShadow({mode: 'open'});
    
    shadow.appendChild(template.content.cloneNode(true));
    
    // Configuration de l'image
    shadow.querySelector('.image').src = this.getAttribute('image');
  }
}

customElements.define('carte-produit', CarteProduit);
</script>

Et l’utilisation :

<carte-produit image="monproduit.jpg">
  <span slot="nom">MacBook Pro</span>
  <span slot="prix">2499€</span>
  <span slot="description">Ordinateur portable professionnel</span>
</carte-produit>

Les slots, c’est comme des emplacements réservés où vous pouvez injecter du contenu.

La différence avec React/Vue

Alors, pourquoi ne pas utiliser React ou Vue ? Bonne question ! Les frameworks sont fantastiques, mais ils ajoutent une couche de complexité :

  • Build process : avec React/Vue, vous devez compiler votre code
  • Bundle size : vous embarquez toute la librairie
  • Learning curve : il faut apprendre le framework en plus

Avec les Web Components, c’est du JavaScript natif. Pas de compilation, pas de framework à charger, et ça fonctionne dans tous les navigateurs modernes (bon, avec quelques polyfills pour les plus anciens).

Et le plus beau ? Vous pouvez utiliser vos Web Components dans une app React, Vue, ou même directement dans WordPress sans aucun problème de compatibilité !

Intégration dans Gutenberg : Adieu JSX, bonjour Web Components

Bon, je dois l’avouer : quand j’ai découvert qu’on pouvait créer des blocs Gutenberg avec des Web Components plutôt qu’avec React et tout le bazar de compilation… ça a changé ma façon de développer ! Fini le build step, fini les erreurs de JSX, on revient aux fondamentaux du JavaScript.

Registrer un Web Component dans WordPress

L’enregistrement d’un bloc Gutenberg avec un Web Component suit la même logique que d’habitude, mais avec une approche différente. Voici comment procéder :

wp.blocks.registerBlockType('monsite/mon-component-block', {
    title: 'Mon Web Component',
    icon: 'admin-tools',
    category: 'common',
    
    edit: function(props) {
        // Création de l'élément Web Component
        const element = wp.element.createElement('my-custom-element');
        element.setAttribute('block-id', props.clientId);
        return element;
    },
    
    save: function(props) {
        return wp.element.createElement('my-custom-element', {
            'data-content': props.attributes.content
        });
    }
});

Attention cependant : votre Web Component doit être défini avant l’enregistrement du bloc (logique, mais on l’oublie parfois !).

Créer l’interface sans build step

C’est ici que ça devient intéressant ! Plus besoin de Webpack ou de Babel pour compiler du JSX. On crée notre interface directement en JavaScript vanilla :

class MyCustomElement extends HTMLElement {
    constructor() {
        super();
        this.innerHTML = `
            <div class="my-component">
                <input type="text" placeholder="Votre texte..." />
                <button>Valider</button>
            </div>
        `;
    }
    
    connectedCallback() {
        const input = this.querySelector('input');
        const button = this.querySelector('button');
        
        button.addEventListener('click', () => {
            this.dispatchEvent(new CustomEvent('content-changed', {
                detail: { value: input.value }
            }));
        });
    }
}

customElements.define('my-custom-element', MyCustomElement);

La beauté de cette approche ? Aucune compilation nécessaire. Vous écrivez, vous sauvegardez, ça marche. Point final !

Gérer les props et les événements

Maintenant, il faut faire communiquer notre Web Component avec WordPress. Pour les propriétés, on utilise setAttribute() et pour les événements, les CustomEvent :

// Dans le bloc Gutenberg
edit: function(props) {
    const { attributes, setAttributes } = props;
    const element = document.createElement('my-custom-element');
    
    // Passer les données au composant
    element.setAttribute('content', attributes.content || '');
    
    // Écouter les changements
    element.addEventListener('content-changed', (event) => {
        setAttributes({ content: event.detail.value });
    });
    
    return element;
}

Bon, je ne vais pas vous mentir : c’est un peu plus verbeux que React parfois. Mais vous avez un contrôle total et zéro dépendance ! Par contre, attention à la gestion du state : contrairement à React, vous devez synchroniser manuellement les attributs WordPress avec l’état de votre composant.

Et voilà ! Votre bloc Gutenberg fonctionne avec des Web Components natifs. Plus simple à debugger, plus léger à charger, et surtout… ça marche dans tous les navigateurs modernes sans polyfill !

Styling et encapsulation : CSS dans le Shadow DOM

Bon, on va parler du truc le plus génial avec les Web Components : l’encapsulation CSS. Fini les conflits de styles entre votre composant et le reste de WordPress ! Le Shadow DOM créé une barrière étanche… enfin, presque.

Styles isolés avec :host et ::slotted

Le Shadow DOM, c’est comme un petit univers CSS parallèle. Vos styles ne sortent pas, et ceux du parent n’entrent pas (sauf exception). Pour styler le composant lui-même, on utilise le sélecteur :host :

:host {
  display: block;
  padding: 20px;
  border-radius: 8px;
  background: #f8f9fa;
}

/* Style conditionnel selon les attributs */
:host([type="warning"]) {
  border-left: 4px solid #ff6b35;
}

Attention avec ::slotted() : il ne fonctionne que sur les éléments directement slottés, pas leurs enfants. C’est une limitation importante à garder en tête.

Variables CSS et communication avec le parent

Les CSS custom properties passent la barrière du Shadow DOM ! C’est notre porte d’entrée pour l’intégration avec WordPress :

:host {
  color: var(--wp-primary-color, #2271b1);
  font-family: var(--wp-font-family, -apple-system, sans-serif);
  --component-spacing: var(--wp-block-spacing, 1rem);
}

Dans votre thème WordPress, vous définissez ces variables :

:root {
  --wp-primary-color: #your-brand-color;
  --wp-font-family: "Your Custom Font";
}

Cette approche permet une communication élégante entre votre composant et l’environnement WordPress.

Gestion du responsive et des thèmes WordPress

Le responsive dans le Shadow DOM suit les mêmes règles… mais avec quelques spécificités. Les media queries fonctionnent normalement, mais attention aux unités relatives qui peuvent poser problème :

:host {
  container-type: inline-size; /* Container queries FTW */
}

@container (max-width: 768px) {
  .component-grid {
    grid-template-columns: 1fr;
  }
}

Pour l’intégration avec les thèmes WordPress existants, pensez à récupérer les CSS custom properties du thème parent. Certains thèmes modernes les exposent déjà (Twenty Twenty-Three, par exemple). Sinon, vous devrez créer un pont JavaScript pour synchroniser les styles.

Un conseil pratique : testez toujours sur plusieurs thèmes WordPress populaires. L’encapsulation peut parfois créer des effets de bord inattendus, notamment avec les thèmes qui utilisent des techniques CSS avancées.

Communication avec l’API WordPress et avantages pratiques

Bon, maintenant qu’on maîtrise la création de Web Components pour WordPress, parlons de la partie qui m’a le plus enthousiasmé : la communication avec l’API REST. C’est là que tout prend vie !

Utilisation de fetch() et wp.apiRequest()

Dans vos Web Components, vous avez deux options principales pour dialoguer avec WordPress. La première, c’est le bon vieux fetch() :

class MyPostsList extends HTMLElement {
  async connectedCallback() {
    try {
      const response = await fetch('/wp-json/wp/v2/posts');
      const posts = await response.json();
      this.renderPosts(posts);
    } catch (error) {
      console.error('Erreur API:', error);
    }
  }
}

Mais WordPress nous offre aussi wp.apiRequest() (quand il est disponible), qui gère automatiquement les nonces et l’authentification. Personnellement, je préfère cette approche car elle simplifie énormément la gestion des permissions.

Gestion de l’authentification et des nonces

Ah, les nonces… Le cauchemar de tout développeur WordPress ! Avec les Web Components, on peut s’en sortir élégamment. Voici ma méthode préférée :

class SecureComponent extends HTMLElement {
  constructor() {
    super();
    this.nonce = wpData.nonce; // Injecté via wp_localize_script
  }
  
  async updatePost(postId, data) {
    const response = await fetch(`/wp-json/wp/v2/posts/${postId}`, {
      method: 'PUT',
      headers: {
        'Content-Type': 'application/json',
        'X-WP-Nonce': this.nonce
      },
      body: JSON.stringify(data)
    });
    return response.json();
  }
}

L’astuce, c’est d’injecter le nonce côté PHP avec wp_localize_script(). Ainsi, votre composant reste autonome mais sécurisé.

Avantages des Web Components vs React

Alors, pourquoi choisir les Web Components plutôt que React ? J’ai testé les deux approches sur plusieurs projets, et voici ce que j’ai observé :

Pas de build : C’est le gros avantage ! Vous écrivez votre composant, vous l’uploadez, ça marche. Fini les pipelines webpack complexes ou les erreurs de compilation mystérieuses.

Performance native : Les Web Components utilisent les API natives du navigateur. Résultat ? Moins de JavaScript à télécharger et une exécution plus rapide. Sur un site e-commerce que j’ai optimisé, on a gagné 200ms de temps de chargement juste en remplaçant quelques composants React par des Web Components.

Réutilisabilité cross-framework : Vos composants fonctionnent partout ! WordPress aujourd’hui, Vue.js demain, Angular après-demain… Ils s’en fichent complètement du contexte.

Limitations actuelles

Néanmoins, soyons honnêtes : tout n’est pas rose. Le support navigateur s’améliore, mais Internet Explorer… bon, on s’en fiche maintenant ! Par contre, certains cas avancés restent complexes.

La gestion d’état globale, par exemple, demande plus de travail qu’avec Redux. Et si vous avez besoin d’un écosystème riche (routing, animations complexes), React reste plus mature.

Recommandations d’usage selon le contexte

Voici mes recommandations basées sur mon expérience :

Utilisez les Web Components quand :

  • Vous développez des widgets simples à moyens
  • La performance est critique
  • Vous voulez éviter les dépendances externes
  • Votre équipe préfère le JavaScript vanilla

Restez sur React si :

  • Vous construisez une application complexe
  • Votre équipe maîtrise déjà l’écosystème React
  • Vous avez besoin de beaucoup de librairies tierces

Pour ma part, j’ai adopté une approche hybride : Web Components pour les éléments d’interface simples, React pour les parties plus complexes. Et franchement, ça fonctionne très bien !