Le développement front-end a beaucoup évolué depuis l’apparition des premières pages web. Aujourd’hui, le développement front-end est dominé par l’utilisation de frameworks Javascript dits modernes, tels que Angular, React.js ou Vue.js. Ces frameworks sont construits sur la notion de composant : une entité autonome, paramétrable via des “props” que l’on peut utiliser et réutiliser dans une application plus globale, ou même dans plusieurs applications différentes.

Pour développer les composants utilisés par nos applications front-end, plusieurs approches sont possibles. Mais l’une d’entre elles semble gagner en popularité : le “Component-Driven Development” (CDD pour les intimes ou Développement piloté par les composants dans la langue de Molière). Le CDD est une approche de type bas vers le haut, où les développements se font du composant vers l’application globale et où le développement des composants se fait de façon progressive en augmentant la complexité à chaque itération, par exemple au fur et à mesure des users stories dans un cadre de travail Agile.

Dans cet article nous allons mettre en œuvre le CDD en utilisant Storybook, un outil de développement qui permet de monter ses composants dans un environnement isolé et contrôlé, en totale indépendance d’une application front-end plus globale. Cela nous permet de nous assurer plus facilement de la ré-utilisabilité et de la testabilité du composant, ce qui est le but recherché par le CDD. Pour comprendre comment mettre en œuvre le CDD en utilisant Storybook, nous allons créer un composant “Carte d’identité” simpliste qui permettra à un utilisateur de renseigner certaines informations, par exemple dans un but hypothétique de les partager lors de rencontres fortuites !

Mise en place du projet Vue.js

Tout d’abord, nous allons créer un projet Vue.js à l’aide de vue-cli. Après avoir installé Node.js et vue-cli, lancer dans un terminal la commande suivante:

vue create identity-card

On pourra choisir “default” à la question “Please pick a preset” pour avoir un environnement de développement le plus simple possible et se focaliser sur le Storybook. Nous obtenons ainsi un nouveau projet Vue.js. Ensuite, nous allons créer un nouveau composant IdentityCard.vue et modifier App.vue pour qu’il utilise notre nouveau composant IdentityCard.vue et vérifier ainsi que tout fonctionne. On se trouve dans l’état suivant après ces différentes actions:

État initial de l’application

On peut vérifier que cela fonctionne bien en lançant la commande :

npm run serve

et en inspectant localhost:8080 à l’aide d’un navigateur internet.

Installation de Storybook et mise en place du CDD

L’installation de Storybook est très simple. Dans un terminal, il suffit de lancer la commande :

npx -p @storybook/cli sb init

Storybook va détecter le framework utilisé (dans notre cas Vue.js) et installer les bonnes dépendances automatiquement. Il n’y a rien de plus à faire ! On peut vérifier que l’installation de Storybook s’est bien passée en lançant la commande suivante :

npm run storybook

En cas de succès, Storybook ouvre un nouvel onglet montrant le Storybook par défaut dans votre navigateur. Dans le cas contraire Google et StackOverflowrestent vos meilleurs amis !

L’installation de Storybook crée deux répertoires: ./.storybook (pour la configuration) et ./stories contenant les stories d’exemples du Storybook par défaut. Nous allons supprimer le répertoire ./stories car nous allons écrire nos stories directement à coté des composants. Ainsi, nous allons créer un fichier identityCard.stories.js dans le répertoire ./src/components que nous allons laisser vide pour le moment. Il nous reste à modifier la configuration de Storybook pour qu’il aille chercher les stories dans le répertoire ./src à la place du répertoire ./stories (qui n’existe maintenant plus !). Pour se faire, nous allons remplacer le contenu de ./.storybook/config.js par le code suivant :

Si nous lançons notre Storybook à l’aide de la commande npm run storybooknous arrivons sur une page nous indiquant que nous n’avons aucune story. Ce qui est normal car nous n’avons défini encore aucune story et que nous avons supprimé les stories par défaut ! Pour créer notre première story, nous allons placer le contenu suivant dans le fichier IdentityCard.stories.js :

Ceci est la façon la plus simple d’écrire une story : la fonction storyOf permet de créer un groupe de storymodule est une variable globale utilisée par webpack pour le hot-replacement. La fonction add permet d’ajouter une story. Son premier argument est le nom de la story et son deuxième argument est une fonction qui retourne un composant Vue.js. Mais cela ne fonctionne pas en l’état. En effet si on l’on inspecte notre Storybook dans notre navigateur, on obtient une page blanche et une erreur dans la console nous indiquant que Vue.js ne trouve pas notre composant IdentityCard.vue, ce qui est normal car nous ne l’avons pas déclaré dans l’instance de Vue.js utilisée par notre Storybook ! Pour résoudre le problème, il convient de rajouter les lignes suivantes dans .storybook/config.js :

import Vue from "vue";
import IdentityCard from "../src/components/IdentityCard.vue";
Vue.component("identity-card", IdentityCard);

Le fichier obtenu est alors le suivant :

On peut alors vérifier que notre Storybook fonctionne à nouveau grâce à la commande npm run storybook ! Ça y est, nous avons écrit notre première story et nous pouvons commencer le développement du composant IdentityCard.vue !

Développement du composant IdentityCard.vue

Notre composant IdentityCard est spécifié de la manière suivante : il doit permettre à un utilisateur de saisir son nomson prénomson âgesa couleur et son film préférés. La carte pourra être modifiable ou en lecture seule. Elle pourra aussi avoir un mode réduit pour prendre moins de place. On peut donc imaginer les props suivantes pour notre composant : canEdit , extended .

La première étape consiste à donner les props au composant IdentityCard.vue et à leur fournir une valeur par défaut. On peut alors implémenter notre composant de façon très sommaire, sans utiliser les props, et arriver par exemple à l’implémentation suivante :

Implémentation de base de IdentityCard.vue

Ce qui rend dans un navigateur le composant suivant :

Rendu pour l’implémentation de base de IdentityCard.vue

Cette implémentation n’utilise volontairement pas les props. Il nous reste maintenant à prendre en compte et à développer le rendu du composant en fonction de la valeur des props qu’il reçoit. Il existe plusieurs façons de procéder. Une première façon, peut-être la plus directe, consiste à implémenter le comportement des boutons pour changer l’état du composant et nous permettre ainsi de voir le composant dans l’état désiré. Cela a au moins deux inconvénients :

  • Il faut faire des actions répétitives à chaque rechargement du composant pour arriver dans l’état voulu.
  • Il faut construire un environnement pour le composant : les données contenants les props et les clic-handlers associés pour changer la valeur de ces props.

Storybook nous permet d’éviter ces deux problèmes en nous proposant des environnements isolés pour monter notre composant avec les différentes valeurs possibles des props. Pour cela, il nous suffit de créer deux nouvelles stories de la façon suivante:

Lorsqu’on ouvre notre Storybook, on peut directement visualiser notre composant dans l’état dans lequel on souhaite travailler. De plus, cela peut s’avérer très utile si le composant à développer se trouvait sur une page longue d’accès dans notre application principale, par exemple en terme de navigation et que notre seul moyen de tester notre composant était d’y accéder dans une application front-end.

Nous pouvons maintenant travailler sur notre composant qui recevra toujours une props canEdit = false même en cas de rechargement de la page dans le cas de la story sélectionnée ci-dessus. Après implémentation de la prise en compte des props, on peut obtenir le composant suivant:

./src/components/IdentityCard.vue — version finale
Storybook — story par défaut
Storybook — story in read-only mode
Storybook — story in reduced mode

Nous avons donc implémenté notre composant sans avoir eu besoin d’un environnement complet incluant les clic-handlers pour modifier la valeur des props données à notre composant. Storybook permet ainsi donc de développer des composants indépendamment d’une application plus globale et ainsi de faciliter le développement piloté par les composants.

Conclusion

D’une grande simplicité à mettre en œuvre dans un projet front-end utilisant un framework Javascript moderne tel que Angular, React.js ou Vue.js, Storybook se révèle être un outil très utile pour aider au développement de nos composants UIs.

Il aide ainsi non seulement à concevoir et à implémenter des composants réutilisables mais peut également servir de documentation pour les développeurs, notamment en montrant les formes du composant en fonction de ses différentes props. C’est d’ailleurs le moyen privilégié de documentation du date-picker de Airbnb.

Mais ceci n’est qu’un petit aperçu de ce que peut faire Storybook Storybook offre en effet de nombreuses possibilités grâce à différents addons qui permettent d’aller encore plus loin dans la construction et l’exploitation d’un Storybook props dynamiquescontainers adaptatifsmontrer le code source des stories… Pour lire des stories, cette fois des articles plutôt que des histoires, sur Storybook, n’hésitez pas à faire un tour sur le compte Medium de Storybook !

François Lê