Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Développement et architecture des Applications Web Modernes
  3. Faire bon usage des Web Components
Extrait - Développement et architecture des Applications Web Modernes Retrouver les fondamentaux
Extraits du livre
Développement et architecture des Applications Web Modernes Retrouver les fondamentaux Revenir à la page d'achat du livre

Faire bon usage des Web Components

Introduction

images/04DP01.png

Standards utilisés pour la création de Web Components

Après plus de trente ans d’existence, et une décennie de débats et expérimentations, la plateforme web permet enfin de réaliser de véritables composants graphiques pleinement réutilisables.

Ces "Web Components" ont ces dernières années fait naître beaucoup d’espoirs et de spéculations. La grande majorité d’entre elles passe cependant à côté de la véritable nature de cette nouvelle technique.

Répondant à des problématiques précises, les Web Components complètent (et parfois remplacent) déjà plusieurs bibliothèques pour tout un ensemble de cas d’usages. Nous sommes cependant très loin de voir les Web Components prendre le pas sur les frameworks et bibliothèques de développement applicatif (si tant est que cela soit possible, voire souhaitable).

De nombreuses solutions furent créées bien avant l’arrivée des Web Components. Adapter ces solutions à des standards qui n’existaient pas au moment de leur conception demande un travail conséquent. Dans certains cas, cette adaptation peut même s’avérer impossible.

React, notamment, repose sur un type de composants très éloignés des Web Components (voir...

Étendre le vocabulaire HTML

Avant toute chose, créer des Web Components consiste à inventer de "nouveaux mots" pour HTML. Le standard de ce langage définit déjà un grand nombre d’éléments, mais tous ne peuvent répondre à nos besoin. Nous allons donc créer de nouveaux éléments personnalisés, c’est-à-dire des Custom Elements, pour reprendre l’expression définie dans le standard HTML.

L’ensemble de l’interface de développement HTML pour les éléments personnalisés est disponible via le seul objet window.customElements, instance de CustomElementRegistry, et n’est constitué que des quatre méthodes suivantes :

  • customElements.define(), pour définir un élément personnalisé

  • customElements.get(), pour renvoyer le constructeur d’un élément personnalisé si celui-ci a déjà été défini

  • customElements.upgrade(), pour "mettre à jour" un élément personnalisé déconnecté du DOM

  • customElements.whenDefine(), pour détecter quand un élément personnalisé donné est défini

Leur utilisation comporte cependant plusieurs particularités importantes, ainsi que des pièges à éviter.

1. Définir un élément personnalisé

Lorsque nous évoquons les spécifications Custom Elements, nous pensons avant tout à la définition de nouveaux éléments HTML non standardisés. Ce premier type d’élément personnalisé est dit "autonome" (Autonomous Custom Element).

Tout élément personnalisé autonome précédemment défini pour un nom donné (par exemple, hello-world) est utilisable comme n’importe quel autre élément HTML :

<hello-world></hello-world> 

Le standard HTML définit également une fonctionnalité supplémentaire, permettant qu’un élément personnalisé étende un élément HTML standard. Les éléments ainsi obtenus sont appelés "élément intégrés personnalisés"...

Créer et utiliser un arbre fantôme

Si un élément personnalisé peut, dans certains cas simples, être considéré comme un composant, il ne constitue pas, à lui seul, un Web Component. Car si le standard Custom Elements permet d’étendre le langage HTML, il ne garantit en rien l’isolation du comportement créé, et donc sa réutilisabilité.

Dans ce livre, nous faisons une distinction claire entre "composants graphiques Web", terme générique désignant toute unité répondant aux exigences de la programmation orientée composants pour le Web, et "Web Component", composant associant la définition d’un élément personnalité et d’un shadow DOM.

Dans d’autre contextes, utiliser le terme "Web Component" pour désigner un ensemble plus ou moins large de techniques destinées à implémenter un composant graphique Web en suivant les normes établies par le W3C et le WHATWG est cependant courant et parfaitement valide.

1. Notions fondamentales

En partant du principe que ce composant peut être réutilisé dans n’importe quel contexte, nous nous retrouvons en effet, dans le cas où nous n’aurions défini qu’un simple élément personnalisé comme dans la section précédente, face à deux problématiques liées au DOM :

1. Tout style défini pour le document est automatiquement appliqué aux enfants de notre élément personnalisé, pouvant ainsi entraîner des conflits et altérer l’apparence du Web Component.

2. Tout code JavaScript hors élément personnalisé effectuant une manipulation du DOM est susceptible de modifier par mégarde le contenu du Web Component.

Le standard Shadow DOM (DOM "fantôme") a été établi exactement pour résoudre ce type de problème, en permettant de créer un nouvel arbre fantôme (shadow tree) séparé de celui du document.

images/04DP03.png

Pour ce faire, il suffit d’appeler la méthode Element.attachShadow(ShadowRootInit init) de l’élément HTML (soit l’élément id="shadow" dans l’exemple suivant)...

Définir le style d’un Web Component

En l’absence de mécanisme permettant une isolation "totale", définir un DOM fantôme pour un Web Component a pour principal avantage d’isoler son style. Cependant, cette isolation a peu d’utilité si nous ne définissons pas également un style spécifique pour ce composant. Pour ce faire, la meilleure solution est généralement de créer directement un élément <style>, d’y définir notre style CSS isolé et de l’ajouter comme premier enfant de la racine fantôme. 

Dans la continuité de l’exemple de la section précédente, nous pouvons ainsi créer un nouveau Web Component AuthorComponent de la manière suivante :

class AuthorComponent extends HTMLElement { 
  constructor() { 
    super(); 
    const shadowRoot = this.attachShadow({ mode: "open" }); 
 
    const style = document.createElement("style"); 
 
    style.textContent = ` 
      p { 
        color: green; 
      } 
    `; 
 
    const text = document.createElement("p"); 
    text.textContent = "- an Anonymous FullWebDev Poet"; 
 
    shadowRoot.appendChild(style); 
    shadowRoot.appendChild(text); 
  } 
} 
 
customElements.define("poem-author", AuthorComponent); 

Ce qui nous permet d’afficher le texte en vert dans notre arbre fantôme.

<div class="red"> 
  <poem-author> 
    <!-- 
    #shadow-root (open) 
      <style>...</style> 
      <p>...</p> 
    --> 
  </poem-author> 
</div> 

1. Style externe

Un projet pouvant comprendre de nombreux Web Components, partager entre eux un style commun s’avère souvent nécessaire....

Templates et composition

Les Web Components étaient initialement conçus sur la base de quatre standards : Custom Elements, Shadow DOM, HTML Templates et HTML Imports. Comme nous l’avons vu dans les sections précédentes de ce chapitre, l’association des deux premiers constitue la base minimum à partir de laquelle nous pouvons garantir une réutilisabilité suffisante pour qualifier un composant de Web Component.

À part quelques rares exceptions, les Web Components sont cependant avant tout destinés à offrir une interface utilisateur. Pour ce faire, nous devons effectuer de nombreux appels à la DOM API. Ce qui peut rapidement constituer un obstacle à la réutilisabilité du composant et provoquer de nombreux problèmes de performance (voir le chapitre Afficher des données dynamiquement).

Les standards HTML Templates et HTML Imports furent tous deux pensés dans le but de faciliter l’écriture et la manipulation du code HTML, et donc de réduire le nombre d’appels à la DOM API.

Le draft HTML Imports fut cependant abandonné en 2016. Repensé sur la base des ES modules, ce document donne naissance en 2019 à la proposition HTML Modules, qui est malheureusement, en 2021, encore à un stade embryonnaire (voir le chapitre Adopter une approche par composants, section Naissance d’un standard).

Dans le cadre des Web Components, les templates HTML perdent une bonne partie de leur intérêt initial une fois privés d’un mécanisme d’import. De ce fait, peu de Web Components utilisent aujourd’hui un template HTML. De tels templates peuvent malgré tout répondre très efficacement à certaines problématiques précises.

Il s’agit par ailleurs d’un concept extrêmement simple, puisque constitué de seulement deux éléments HTML, <template> et <slot>, dont la définition dans le standard tient en à peine plus de 1 000 mots (600 dans la version développeur), codes d’exemples compris, et peut donc être lue en moins de cinq minutes27.

1. <template>

images/04DP07.png

<template> étant un élément de scripting (au même titre que <script> et <noscript>), il ne définit en lui-même...

Attributs et propriétés

Jusqu’à présent, nous n’avons présenté que des composants quasi statiques, effectuant un unique rendu lors de leur création. De tels composants permettent bien d’améliorer la maintenabilité d’une application web, en découpant notre interface en différentes "briques" autonomes réutilisables.

Ces briques demeurent cependant simplistes et ne permettent pas de couvrir l’ensemble de nos besoins en termes de réutilisabilité.

1. Principe : suivre la logique du standard HTML

La programmation orientée composant nous impose, pour garantir une réutilisabilité maximale, de définir clairement les interfaces exposées par un composant. La seule connaissance de celles-ci (le plus souvent grâce à une documentation) permet d’ignorer l’implémentation sous-jacente.

Dans les sections précédentes, nous avons étudié trois types d’interfaces exposées par un Web Component :

  • des classes CSS (voire des attributs), permettant d’indiquer un "contexte" associé à un ensemble de règles CSS,

  • des propriétés personnalisées, permettant de définir plus finement leur style malgré le shadow DOM,

  • des slots, permettant de partiellement définir le contenu du Web Component

Toutes ces techniques, cependant, sont essentiellement liées à de pures problématiques de présentation. Manque donc ici une API permettant de modifier dynamiquement l’état de notre composant.

Or, tout élément HTML, qu’il soit standard ou non, dispose de deux interfaces permettant de modifier son état, son rendu, et son comportement : ses attributs HTML et ses propriétés DOM.

Dans le cas d’un élément <input>, il est par exemple possible de spécifier le type de contrôle souhaité via l’attribut type, tandis que la propriété value permet d’en récupérer ou d’en modifier la valeur.

Un élément personnalisé étant avant tout un élément HTML, les attributs et propriétés d’un Web Component peuvent, et doivent, être utilisés...

Limites des Web Components

Le 22 mai 1992, la toute première publication W3C relative aux Web Components était introduite par le paragraphe suivant31 :

« Le modèle de composant pour le web [vise à] permettre aux auteurs d’applications web de définir des widgets avec […] une facilité de composition et de réutilisation inaccessible via les bibliothèques JavaScript actuelles. »

Les Web Components étaient porteurs d’une promesse : permettre d’étendre HTML, simplement et sans bibliothèque dédiée. En mettant l’accent sur le réutilisabilité, l’idée même de ce standard était moins de permettre une large adoption de la programmation orientée composant pour les applications web que d’améliorer HTML lui-même. Les spécifications du langage n’étant destinées qu’à définir un ensemble très limité d’éléments, les Web Components devaient permettre à n’importe quel intégrateur d’avoir accès à un choix immense de nouveaux "widgets" performants et simples d’usages transformant la création de pages web en un grand jeu de Lego dénué des défauts des plug-ins jQuery et consorts.

En 2021, cette promesse n’est...

Références

1. EBNF Notation [En ligne]. Disponible sur : https://www.w3.org/TR/xml/#sec-notation (consulté le 22 novembre 2020).

2. WHATWG HTML 4.13.2 Requirements for custom element constructors and reactions [En ligne]. Disponible sur : https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-conformance (consulté le 22 novembre 2020).

3. NIWA R. rniwa comment on issue 509 - The is="" attribute is confusing? Maybe we should encourage only ES6 class-based extension. [En ligne]. GitHub WICG/webcomponents. 6 juillet 2016. Disponible sur : https://github.com/WICG/webcomponents/issues/509 (consulté le 22 novembre 2020).

4. LISKOV B., WING J. M. Family Values: A Behavioral Notion of Subtyping. [s.l.] : ACM Transactions on Programming Languages and Systems, 1994.

5. « 4.9. Interface Element - attachShadow ». In : DOM Standard [En ligne]. [s.l.] : [s.n.], [s.d.]. Disponible sur : https://dom.spec.whatwg.org/#dom-element-attachshadow (consulté le 23 novembre 2020).

6. tc39/proposal-class-fields [En ligne]. 14 mai 2017. Disponible sur : https://github.com/tc39/proposal-class-fields (consulté le 23 novembre 2020).

7. « Public class fields ». In : Chrome Platform Status [En ligne]. [s.l.] : [s.n.], [s.d.]. Disponible sur : https://www.chromestatus.com/feature/6001727933251584 (consulté le 23 novembre 2020).

8. « Private class fields ». In : Chrome Platform Status [En ligne]. [s.l.] :...