Webcomponent : éviter les collisions de styles entre React, Vue et Angular

Un webcomponent transforme une interface récurrente, comme un bouton enrichi, une fiche produit, un champ de recherche ou un lecteur média, en balise HTML autonome. Il réunit le comportement et, si nécessaire, l’apparence du composant pour le rendre prévisible dans plusieurs applications, y compris lorsqu’elles reposent sur des frameworks différents.
Un webcomponent, concrètement, qu’est-ce que c’est ?
Les Web Components regroupent des standards du navigateur pour créer des composants d’interface réutilisables en JavaScript natif. Au lieu d’assembler à chaque utilisation du HTML, du CSS et des gestionnaires d’événements, on définit un élément personnalisé, puis on l’emploie comme une balise classique, par exemple <product-card></product-card>.
Testez vos connaissances sur les Web Components
Cette approche répond à un problème fréquent dans les grands sites : une même fonctionnalité doit parfois fonctionner dans plusieurs environnements. Une équipe peut maintenir un site éditorial en HTML classique, un espace client en Angular et un tunnel d’achat en React. Un webcomponent fournit alors un contrat d’usage stable, avec des attributs en entrée, des événements en sortie et une balise comprise par le navigateur.
Les trois briques du standard
Les Custom Elements servent à déclarer de nouvelles balises HTML et à leur associer une classe JavaScript. Le Shadow DOM crée une frontière autour de l’arbre interne du composant, notamment pour protéger ses styles. Les HTML Templates permettent de préparer une structure réutilisable avec <template>, tandis que les <slot> accueillent le contenu fourni par la page qui utilise le composant.
Ces briques peuvent être utilisées ensemble ou séparément. Un élément personnalisé très simple n’a pas toujours besoin d’un Shadow DOM. À l’inverse, une carte complexe intégrée dans plusieurs produits gagne souvent à encapsuler son CSS et son balisage interne. Le choix dépend donc du niveau d’isolation et de personnalisation attendu.
Pourquoi les adopter dans une architecture web ?
Le premier bénéfice est la réutilisabilité. Le composant embarque son rendu, ses interactions et son API. Il peut être distribué comme une bibliothèque interne sans imposer un framework particulier. Cette organisation réduit les duplications et les divergences : le bouton de consentement ou le sélecteur de date conserve les mêmes règles métier partout où il est utilisé.
Créer des composants web réutilisables avec les Web Components : La documentation officielle MDN explique les technologies et API pour concevoir des éléments personnalisés, encapsulés et réutilisables.
- Encapsulation : les styles internes risquent moins d’être écrasés par la feuille CSS de l’application hôte.
- Interopérabilité : un composant fondé sur des API natives peut être chargé dans une page en JavaScript natif comme dans une application moderne.
- Maintenance : l’équipe documente une balise, ses attributs, ses propriétés et ses événements plutôt que plusieurs implémentations parallèles.
- Progressivité : il est possible de commencer par un composant isolé, sans réécrire l’ensemble d’un site.
Il faut toutefois éviter d’y voir une solution universelle. Les Web Components n’imposent ni gestion d’état globale, ni routage, ni stratégie de rendu côté serveur. Un framework peut rester pertinent pour structurer une application riche. Le webcomponent devient alors une unité d’interface partageable, pas nécessairement le socle de toute l’architecture.
Créer un premier élément personnalisé sans dépendance
Un composant utile commence par une responsabilité étroite. Prenons un encart d’alerte capable d’afficher un message et une variante visuelle. Le nom de la balise doit contenir un tiret. Cette règle des éléments personnalisés évite les conflits avec les balises HTML existantes.
Définir la classe et enregistrer la balise
Le principe est simple : une classe étend HTMLElement, puis le navigateur l’associe à un nom avec customElements.define(). Dans un fichier JavaScript chargé par la page, l’ossature peut s’écrire ainsi : class AppAlert extends HTMLElement { connectedCallback() { this.textContent = this.getAttribute('message') || 'Information'; } } customElements.define('app-alert', AppAlert);. La page peut ensuite contenir <app-alert message="Votre demande a été envoyée."></app-alert>.
connectedCallback() s’exécute lorsque l’élément est inséré dans le document. C’est l’endroit adapté pour créer le rendu initial et brancher les événements. D’autres méthodes du cycle de vie permettent notamment de réagir à la suppression de l’élément ou à l’évolution d’un attribut observé. Gardez ces traitements courts et nettoyez les écouteurs ajoutés à des objets externes.
Ajouter un Shadow DOM et un template
Pour empêcher qu’un style global du type button { ... } ne modifie l’interface interne, attachez une racine d’ombre avec this.attachShadow({ mode: 'open' }). Vous pouvez ensuite injecter un template contenant le HTML et le CSS du composant. Un slot est utile lorsque le consommateur doit fournir un contenu variable, comme un libellé, une icône ou une description.
L’encapsulation ne dispense pas de concevoir une API claire. Les attributs conviennent aux valeurs simples et déclaratives ; les propriétés JavaScript sont plus adaptées aux objets ou aux tableaux. Pour informer l’application hôte d’une action utilisateur, émettez un événement personnalisé avec CustomEvent. Prévoyez, si nécessaire, sa propagation hors du Shadow DOM.
Les styles isolés ne doivent pas compliquer l’intégration
L’isolation CSS peut masquer un point essentiel : un composant parfaitement fermé devient parfois difficile à intégrer dans un design system. Le Shadow DOM protège des collisions, mais il limite aussi l’accès direct aux sélecteurs externes. Prévoyez donc des points de personnalisation explicites : propriétés CSS personnalisées, attributs de variante, parties exposées via part ou emplacements via slot. Cette organisation évite deux écueils : le composant fragile que n’importe quelle règle CSS peut casser et la boîte noire impossible à harmoniser avec la charte graphique.
Rendre le composant accessible dès sa conception
Un webcomponent n’est pas automatiquement accessible parce qu’il repose sur des API natives. Utilisez des éléments sémantiques à l’intérieur, comme un vrai button pour une action cliquable, et non un simple div. Gérez le focus clavier, les intitulés visibles ou accessibles, les états désactivés et les messages dynamiques. Si le composant ouvre une fenêtre ou un menu, son cycle de focus et son comportement avec la touche Échap doivent faire partie de son contrat fonctionnel.
Web Components ou composants React, Vue et Angular ?
La différence majeure tient au niveau d’abstraction. React, Vue et Angular fournissent un modèle complet de composants, avec leurs mécanismes de rendu, d’état et d’outillage. Les Web Components reposent sur les capacités standard du navigateur. Ils sont donc intéressants lorsqu’un même composant doit fonctionner avec plusieurs choix techniques ou être intégré chez des partenaires.
| Approche | Point fort | Point de vigilance |
|---|---|---|
| Web Components | Interopérabilité et API HTML standard | Outillage et conventions à définir par l’équipe |
| React, Vue ou Angular | Écosystème cohérent pour l’application | Réutilisation directe plus dépendante du framework |
| Bibliothèque de composants propre au projet | Intégration immédiate dans une stack unique | Migration et partage plus coûteux hors de cette stack |
Dans React, Angular ou Vue, l’intégration passe généralement par l’utilisation de la balise personnalisée dans le template ou le JSX. Les propriétés complexes et les événements personnalisés méritent des tests ciblés, car la manière de les transmettre ou de les écouter dépend de l’outil. Documentez toujours les attributs acceptés, les propriétés publiques, les événements émis et les styles personnalisables.
Déployer sans transformer le projet en laboratoire
La migration la plus sûre consiste à choisir un composant transverse mais peu critique, comme un bandeau d’information, une carte de profil ou un bouton de contact. Écrivez son API avant son apparence, testez-le dans les pages qui l’accueillent, puis recueillez les retours des équipes consommatrices. Cette méthode révèle rapidement les besoins de thèmes, de traduction, de télémétrie ou de compatibilité avec le rendu côté serveur.
- Délimitez une responsabilité fonctionnelle unique et un nom de balise stable.
- Définissez les attributs, propriétés, événements et variantes CSS autorisés.
- Testez le composant isolé, puis dans chaque application cible.
- Vérifiez la navigation au clavier, l’utilisation avec des lecteurs d’écran et le comportement sur petits écrans.
- Publiez une documentation avec des exemples d’intégration réellement copiables.
Les navigateurs modernes prennent en charge les technologies fondamentales des Web Components. Pour des contraintes particulières ou des environnements plus anciens, vérifiez précisément les navigateurs visés et envisagez un polyfill uniquement lorsqu’il répond à un besoin identifié. L’adoption repose sur des composants fiables, documentés et assez souples pour être utilisés sans surprise, plutôt que sur une réécriture massive du projet.