Retour à l'accueil

Problèmes des web components : performance et API

L'article analyse les principaux problèmes des web components : boilerplate excessif pour les propriétés, faible performance due au proxy hôte, enregistrement global avec conflits et inconvénients Shadow DOM. Benchmarks et exemples de code sont fournis.

Pourquoi les web components sont lents : benchmarks et code
Advertisement 728x90

Les défis de performance et d'API des composants web

Créer un composant web avec une seule propriété nécessite une quantité importante de code en utilisant l’API Custom Elements. L’implémentation de base ne prend en charge que les attributs de type chaîne, ce qui oblige à sérialiser les autres types de données.

Exemple de composant minimal :

class MyFoo extends HTMLElement {

	_bar = 0
	get bar() {
		return this._bar
	}
	set bar( next ) {
		this.setAttribute( 'bar', next )
	}
	
	static observedAttributes = [ 'bar' ]
	attributeChangedCallback( name, prev, next ) {
		this[ '_' + name ] = next
	}
	
}

globalThis.customElements.define( 'my-foo', MyFoo )

Pour supporter les nombres, on ajoute une sérialisation JSON avec un indicateur _muted_ pour éviter la récursion :

Google AdInline article slot
class MyFoo extends HTMLElement {

	_bar = 0
	get bar() {
		return this._bar
	}
	set bar( next ) {
		this._bar = next
		this._muted_ = true; try {
			this.setAttribute( 'bar', JSON.stringify( next ) )
		} finally { this._muted_ = false }
	}
	
	_muted_ = false
	static observedAttributes = [ 'bar' ]
	attributeChangedCallback( name, prev, next ) {
		if( this._muted_ ) return
		this[ '_' + name ] = JSON.parse( next )
	}
	
}

Cela introduit des problèmes d’échappement des chaînes d’attributs et exige des couches d’abstraction supplémentaires pour les dates, les objets et autres types.

Performance : les microsecondes coûtent des frames

Les composants web sont bien plus lents que les objets JS classiques en raison du proxy au runtime. Comparaison du temps de création :

  • Objet JS classique : ~0,01 μs
  • Composant web : ~1–3 μs

Mille composants prennent entre 1 et 3 ms à être créés — une part significative du budget de 16 ms par frame. Les modifications de propriétés consomment aussi des microsecondes :

Google AdInline article slot
  • Affectation JS simple : nanosecondes
  • Setter de composant web : microsecondes

La cause principale est l’échange constant de données entre JS et le runtime C++ du navigateur, bloquant l’inlineage JIT. En mémoire : 124 octets par composant web trivial contre 16 octets pour un objet JS.

Enregistrement global et conflits de noms

L’enregistrement des composants est global et irréversible tant que l’onglet n’est pas fermé :

customElements.define( 'ya-button', YandexButton )
// ...
customElements.define( 'ya-button', YahooButton ) // 💥 Erreur : nom déjà utilisé

Les conflits de noms rompent la modularité. Bien que CustomElementRegistry dans Shadow DOM aide partiellement, les polyfills ne sont pas disponibles, et fusionner les registres demande une gestion de namespace.

Google AdInline article slot

Alternatives :

  • Un registre fractal global comme DNS
  • VerLess — mise à jour sans rupture de compatibilité

Hooks de cycle de vie et Shadow DOM

connectedCallback/disconnectedCallback se déclenchent à chaque mouvement du composant — même lorsqu’il reste à la même place — provoquant des cascades dans tout l’arbre. Cela entraîne des tâches asynchrones inutiles.

Shadow DOM assure une isolation mais complique le style : adoptedStyleSheets exigent des imports dynamiques de feuilles de style externes. Les noms d’éléments doivent être strictement au format kebab-case, ce qui entre en conflit avec les éléments DOM standards.

Ce qui compte vraiment

  • Performance : les composants web sont 100 à 1000 fois plus lents que les objets JS en raison du proxy hôte
  • Code boilerplate : la sérialisation/désérialisation est obligatoire pour les propriétés non chaînes
  • Enregistrement : global, irréversible, sujet aux conflits de noms
  • Cycle de vie : les hooks se déclenchent lors des déplacements, causant des cascades
  • Shadow DOM : complexifie la personnalisation des styles et le polyfilling

Les composants web ne supportent pas le typage statique TypeScript ni la réactivité intégrée, rendant indispensable l’utilisation de frameworks pour les applications réelles.

— Editorial Team

Advertisement 728x90

Lire ensuite