Web Components : la promesse des composants universels enfin tenue
Depuis l’émergence de React en 2013, les composants sont devenus le paradigme dominant du développement frontend. Mais React, Vue et Angular ont chacun leur propre modèle, incompatible avec les autres. Un composant React ne peut pas être utilisé dans une application Vue — et vice versa.

Les Web Components sont la réponse native des standards web à ce problème. Ils permettent de créer des composants d’interface encapsulés et réutilisables, basés sur des APIs nativement supportées par tous les navigateurs modernes, sans dépendance à aucun framework. Un Web Component peut être utilisé dans React, Vue, Angular, Svelte ou un simple fichier HTML — sans modification.
Les trois piliers des Web Components
Custom Elements
L’API Custom Elements permet de définir vos propres balises HTML avec un comportement JavaScript associé :
class MyButton extends HTMLElement {
connectedCallback() {
this.innerHTML = `<button>${this.getAttribute('label') || 'Cliquer'}</button>`;
this.querySelector('button').addEventListener('click', () => {
this.dispatchEvent(new CustomEvent('my-click', { bubbles: true }));
});
}
}
customElements.define('my-button', MyButton);
// Utilisation dans n'importe quel HTML :
// <my-button label="Valider"></my-button>
Shadow DOM
Le Shadow DOM crée un arbre DOM encapsulé, isolé du DOM principal. Les styles définis dans un Shadow DOM n’affectent pas le reste de la page, et les styles externes n’affectent pas le composant. C’est l’encapsulation par conception :
class MyCard extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
:host { display: block; border: 1px solid #ddd; border-radius: 8px; }
.title { font-size: 1.25rem; font-weight: bold; }
</style>
<div class="title"><slot name="title"></slot></div>
<slot></slot>
`;
}
}
HTML Templates et Slots
L’élément <template> permet de définir des fragments HTML inactifs, non rendus, qui peuvent être clonés et instanciés. Les <slot> permettent aux utilisateurs du composant d’injecter leur propre contenu dans des zones définies.

Avantages des Web Components
- Interopérabilité universelle : fonctionnent dans n’importe quel framework ou sans framework
- Encapsulation CSS : zéro conflit de styles avec le Shadow DOM
- Natif navigateur : pas de dépendance, pas de bundle JavaScript supplémentaire
- Longévité : basé sur des standards W3C stables, indépendant des cycles de vie des frameworks
- Idéal pour les design systems partagés entre plusieurs applications avec des stacks différentes
Limites et cas d’usage adaptés
Les Web Components ne sont pas une solution universelle :
- Le rendu côté serveur (SSR) est plus complexe qu’avec les frameworks modernes — des solutions comme Declarative Shadow DOM commencent à adresser ce point
- Pour des interfaces complexes avec beaucoup d’état réactif, React ou Vue offrent un modèle mental plus productif
- L’écosystème d’outils (DevTools, testing) est moins mature que celui des frameworks
Les Web Components brillent dans des cas spécifiques :
- Design systems partagés entre plusieurs équipes et stacks différentes
- Widgets autonomes embarqués dans des sites tiers (chat widget, player audio)
- Composants de bas niveau très stables (boutons, modales, tooltips)
- Applications web à long terme où l’indépendance aux frameworks est stratégique
Lit : la bibliothèque légère pour développer des Web Components
Lit (anciennement LitElement, par Google) est la bibliothèque de référence pour développer des Web Components avec du confort de développement :
import { LitElement, html, css } from 'lit';
class MyCounter extends LitElement {
static properties = { count: { type: Number } };
static styles = css`:host { display: block; } button { padding: 8px; }`;
constructor() { super(); this.count = 0; }
render() {
return html`
<button @click="${() => this.count++}">
Clics : ${this.count}
</button>
`;
}
}
customElements.define('my-counter', MyCounter);

Lit apporte la réactivité, les templates déclaratifs et le hot-reload sans les 40 Ko d’un framework complet. Le bundle de Lit fait environ 6 Ko minifié-compressé.
Erreurs fréquentes à éviter
- Tout encapsuler dans le Shadow DOM : certains composants (formulaires, tableaux) interagissent mal avec le Shadow DOM et les styles globaux
- Attributs vs propriétés : les attributs HTML sont des chaînes, les propriétés JavaScript peuvent être n’importe quel type. Gérer les deux proprement est une source fréquente de bugs
- Accès direct au DOM externe depuis l’intérieur d’un composant : briser l’encapsulation avec des querySelector en dehors du shadow root
- Oublier le cycle de vie : connectedCallback, disconnectedCallback et attributeChangedCallback sont les hooks fondamentaux à maîtriser
Conclusion
Les Web Components ont mis du temps à tenir leur promesse — les lacunes initiales du Shadow DOM et du SSR ont freiné leur adoption. En 2024, les standards ont mûri et des bibliothèques comme Lit offrent un excellent DX. Pour les design systems partagés et les composants à longue durée de vie, les Web Components sont un choix architectural solide et pérenne.
Questions fréquentes sur
Web Components natifs
Oui. Custom Elements, Shadow DOM et HTML Templates sont supportés nativement par Chrome, Firefox, Safari et Edge depuis 2018-2020. Aucun polyfill n'est nécessaire pour les projets ciblant des navigateurs modernes.
Oui. React peut intégrer des Web Components nativement (avec quelques ajustements pour la gestion des événements). Vue les supporte nativement. C'est précisément l'intérêt des Web Components : ils fonctionnent dans n'importe quel contexte.
Non, en général. La migration n'a de sens que pour des composants très stables et à usage transversal entre plusieurs applications. Les nouveaux projets mono-stack tirent moins de valeur des Web Components que des frameworks spécialisés.



