Jan

Construire un Design system

Dans le sillage du billet précédent, cet article s’oriente sur le volet technique sur notre façon de construire et déployer un Design System.

Les objectifs :

  • organiser le train de release ;
  • poser le socle du projet ;
  • concevoir et déployer une version.

Rythmer la construction : Le Backlog et la DoD

Dans la partie “Ai-je réellement besoin d’un Design System ?”, il faut comprendre que la démarche vers un Design System ne peut se construire qu’avec une approche produit : de quoi a besoin mon écosystème applicatif pour garantir une expérience utilisateur unifiée ?

Ce type de besoin épouse naturellement les méthodologies agiles pour une construction incrémentale dirigée par la valeur. Peu importe le framework agile choisi, nous avons retenu deux éléments qui nous paraissaient essentiels à la construction de ce produit :

  • le backlog pour définir et formaliser notre base de discussion et de travail ;
  • la Definition of Done pour certifier de l’implémentation et de la disponibilité d’un composant pour une version.

 

Pourquoi est-ce si important d’avoir au moins ces deux éléments pour avancer ? En pratique, il est difficile de convaincre de l’intérêt majeur d’un Design System au début de sa construction. De ce fait, les équipes dédiées sont souvent minimalistes. La nôtre l’était et nous avons donc réduit nos pratiques/assets agiles au minimum. Au fur et à mesure de nos versions applicatives, nous vérifiions soigneusement l’intégrité et la valeur apportée de ces deux éléments. C’est grâce à cette rigueur que le rythme de construction du produit a naturellement émergé.

Storybook, un Design System « like »

Pour commencer, notre but est d’obtenir une documentation exhaustive et des ressources compatibles à l’utilisation ou non de framework web. Nous prônons également une intégration des ressources en mode Content Delivery Network (CDN) pour faciliter les travaux de mises à jour (modification dans le fichier index.html) et alléger des applications de plus en plus conséquentes. Nous avons donc essayé d’avoir un livrable inclusif en termes d’infrastructure, de niveau technique et de navigateur (*).

Storybook est le choix qui a naturellement émergé des réflexions de l’équipe technique.

« An open source tool for developing UI components in isolation for React, Vue, Angular, and more. It makes building stunning UIs organized and efficient » – Storybook team

Il nous a surtout permis de formaliser nos premières démonstrations.

Pour illustrer le propos dans le reste de l’article, l’historique du dépôt Github https://github.com/spectoor/build-ds évolue en fonction des commandes et des développements réalisés.

Sans plus attendre, “soyons étonnés” : npx sb init –type html && npm run storybook (**)

Storybook

Impressionnant ! En deux commandes, vous vous retrouvez avec quelques composants exemples assez fournis pour pouvoir vous projeter dans votre réalisation (le commit associé). Cependant, nous avons jugé que l’arborescence actuelle du répertoire stories n’est pas très adéquate au développement d’un Design System. Nous avons donc essayé de séparer le code source relatif à la documentation (cf. tests/stories) de celui relatif aux composants.

La configuration Storybook

D’une configuration HTML5/CSS3, nous sommes passés à une stack technique plus moderne HTML5/SCSS/TS pour doper les capacités techniques du Design System (le commit associé).

Pour cela, nous avons enrichi le fichier .storybook/main.js avec :

  • l’addon a11y pour vérifier l’accessibilité des composants ;
  • la propriété webpackFinal en ajoutant les resolvers et les transpillateurs nécessaires.

 

De plus, nous avons créé un fichier .storybook/preview-head.html qui permet d’ajouter le chargement des ressources externes dans l’application Storybook.

Refactoring de l’arborescence

Dans le dossier stories, la description de l’écosystème d’un composant (HTML, CSS, story) y est à plat. Cela reste lisible pour les trois composants fournis. Mais séparer la documentation du code source nous permet de gagner en maintenabilité (le commit associé).

Cette étape est importante car elle fait émerger les premières questions de conception : quelles sont les sources qui généreront les ressources statiques ? Comment générer les ressources statiques ? Comment sont-elles utilisées dans l’application Storybook ? Est-il possible ou devons nous avoir un fichier de configuration pour l’application de production et de développement ?

Refactoring des stories

Dans le sillage de la nouvelle stack technique, ajustons les stories avec du Typescript (le commit associé).

Sur cette étape, il est fréquent de modifier le paramétrage des stories en fonction des addons ajoutés et des différences de norme entre langages. Quelques pistes de refactoring :

  • modifier les titres des stories (arborescence du menu de l’application Storybook)
  • créer des stories plus unitaires pour des besoins de testing et/ou de lisibilité.

 

Refactoring du code source

Dans le dossier src, nous pouvons alors migrer le code source sur la nouvelle stack (le commit associé).

Sur cette étape, il est intéressant de se focaliser sur les normes de développement. Quelques pistes de refactoring :

  • conception applicative (atomic design, web components, etc.) ;
  • utiliser une méthodologie de nommage CSS ;
  • construire un type de données pour les argTypes en fonction des composants.

 

En bref

Une des forces de cet outil est la mise à disposition de plugins permettant d’offrir des interactions et des métriques intéressantes (accessibilité, variations dynamiques, etc.).

Storybook est si riche qu’il pourrait être qualifié de Design System. Quelques bémols si on s’arrêtait sur cette solution :

  • la contribution à la documentation n’est pas aisée pour les designers·euses (Markdown, Git) ;
  • les éléments HTML affichés sont au format story ;
  • l’interface web est standard, peu de latitude pour la personnaliser ;
  • l’organisation en story contraint fortement la hiérarchisation de l’information.

 

Nous avons de ce fait ajouté une dimension de documentation beaucoup plus riche et souple en complément du livrable Storybook(***).

(*) Euh… pas en dessous de IE11, faut pas déconner non plus.

(**) Même si la documentation fait clairement mention de ne pas le faire tourner dans un projet vide, cela fonctionne avec la version 6.1.0

(***) Une alternative pour aller plus loin avec la version React ici

Industrialiser un Design System : les possibilités

Pouvoir faire évoluer votre Design System garantit son adaptabilité et une meilleure adhésion des projets/applications qui l’utiliseront. Cette étape est incontournable pour une mise à l’échelle réussie de votre produit. De plus, la e-réputation du produit doit être garantie par :

  • une obsession à la non-régression ;
  • une facilité pour la montée de version.

 

Ce qui est intéressant ici, c’est qu’en un fichier de configuration et quelques scripts npm plus tard, nous avons rendu ces choses possibles.

Construction et déploiement

Notre artefact construit est composé de deux éléments : les ressources du Design System et un bundle Storybook (le commit associé).

Schéma de construction des artefacts

Nous avons choisi une configuration webpack séparée pour homogénéiser avec ceux de Storybook et avoir une distinction claire entre bundle de développement/production Storybook et bundle de production des ressources statiques.

Les plugins utilisés :

  • mini-css-extract-plugin pour minifier la feuille de style ;
  • webpack.LoaderOptionsPlugin pour configurer l’autoprefixer CSS
  • webpack.BannerPlugin pour ajouter une en-tête commune sur les fichiers générés.

 

Les loaders utilisés :

  • babel-loader pour une transpilation Typescript en ES2015 ;
  • sass-loader pour les fichiers de styles en SCSS ;
  • postcss-loader pour optimiser les styles ;
  • css-loader pour récupérer les styles.

Pour construire le bundle Storybook, rien de plus simple => npm run build-storybook.

La commande génère les fichiers web statiques que vous pouvez servir avec un http-server ou encore un nginx. 

Sur la partie déploiement, nous réalisons une copie de cet artefact sur un bucket S3 AWS :

aws s3 sync –cache-control= »public, max-age=31536000, must-revalidate » $ARTIFACT_SOURCE_PATH/ s3://$BUCKET_NAME

Avoir choisi la mise à disposition en mode CDN impose des contraintes en termes de configuration. En effet, il est important de ne pas oublier d’optimiser la politique de cache et de vérifier la sécurisation des accès. Il faut également prévoir une arborescence de versionning du type https://my-design-system.com/2.0.0/css/style.min.css à l’image de références du CDN telle que cdnjs ou encore unpkg.

Story ? Dis ouistitis !

Encore un super plugin Storybook qui nous donne une corde supplémentaire à notre arc : storycap. C’est un outil de capture qui permet de réaliser des “photos” de stories avec des variantes possibles (interactions et taille de viewport). Combiné avec un outil de différentiel d’image (notre champion sera pixelmatch), nous obtenons une solution de test visuel rapide pour un environnement de développement ou une chaîne d’intégration continue.

Une commande et le tour est joué : npx storycap http://localhost:6006

Une image PNG est alors créée pour chaque story lancée (le commit associé).

Important : storycap utilise en headless soit puppeteer ou un navigateur chromium. Votre projet, machine ou image docker devra donc avoir une installation fonctionnelle (plus de détails ici). Des captures d’écran en mode sans fenêtre ? Oui, c’est une fonctionnalité native des API navigateur pour faciliter l’automatisation des tests en ligne de commande. 

Vous avez aussi la possibilité de piloter vos stories en mode “managed”. On y retrouve une finesse d’interactions et de personnalisations proche d’un Cypress ou Protractor. Mais la conception du test est complètement différente : vous ne coderez qu’une configuration, un decorator Storybook pour faire varier une story. Une phase de refactoring est donc nécessaire pour que vos stories décrivent directement les cas d’utilisation à tester (le commit associé).

Le test visuel fait parti des possibilités de test mis en avant par l’équipe Storybook. Pourquoi ce choix ? Ayant fait les frais de deux ans de tests e2e via Protractor, j’ai toujours cette réticence à leurs mises en place car le coût de réalisation au regard de leur valeur ajoutée en termes de non-régression est souvent trop déséquilibrée.

Ce qui est intéressant dans le test visuel, c’est que l’assertion devient graphique et non codée. Elle n’est donc pas créé par le·la développeur·euse. Deux avantages à cela :

  • effort de développement en moins ;
  • fiabilité du test accrue.

Visual testing

Sources : storybook.org (cliquer sur l’image si elle ne s’anime pas)

 

Il ne faut pas se leurrer, au bout de 7h de boulot et un maudit test qui est toujours rouge, on a tendance à emprunter des chemins de traverse (****).

Mais comment est donc générée l’assertion ? Le test visuel nécessite de maintenir une base de connaissances antérieure du composant testé. Il ne peut donc être que non-régressif par définition.

Maintenir la base de connaissance peut prendre plusieurs formes:

  • maintenir des versions de l’application Storybook en ligne;
  • utiliser les références de versionning de code pour recréer l’application Storybook dans un conteneur ;
  • utiliser une solution SaaS (chromatic, viswiz, percy, etc.).

 

Les solutions SaaS proposent à la fois du hosting des versions de votre Storybook et des captures relatives à ces versions. Elles proposent également une interface de collaboration intéressante pour récolter les feedbacks UI.

Sources : chromatic.com

 

Pour le réaliser sur le poste de développement, nous créons deux dossiers associés à deux versions à comparer (le commit associé).

Le script Node.js visual-testing.js permet alors de comparer les images prises et créer une image différentielle.

 

Image V1

Image V1

Image V2

Image V2

Delta ImageV1 ImageV2

Delta ImageV1 ImageV2

Sources : npmjs.com

(****) Ne me regarde pas comme ça. Je l’ai fait, tu l’as fait et le·la développeur·euse à côté de toi aussi l’a fait.

Publier le Design System

Maintenant que la CI est en place et que la finalisation de la version est presque bouclée, votre build révèle des régressions graphiques. Il faut donc évaluer si les changements opérés sont maîtrisés par l’équipe.

L’équipe a fait le choix de faire cela autour d’une table et un portable ; plus simple et rapide en termes de collaboration. Il y a bien sûr des outils SaaS qui mettent à disposition une zone d’échange où chacun peut contribuer de manière autonome (interface web, notifications, etc.).

L’équipe ayant ajusté les derniers éléments de la version, elle peut enfin fusionner le travail et pousser cette version majeure en production.

Maintenant c’est que du bonus : mise à jour de la documentation, communication de la nouvelle version, tour d’honneur, bière de fin de sprint… Vous êtes fin prêt à démarrer une nouvelle itération.

Le mot de la fin

Le concept de Design System est malheureusement peu valorisé par la communauté technique des artisans d’interface utilisateur. Ce sujet reste pour le moment diffusé par d’excellents designers·euses et initié dans les entreprises par ces mêmes profils.

La voie ouverte par des initiatives open-source telles que Storybook est peut-être l’opportunité pour les développeurs·euses d’y plonger et de donner une dimension supplémentaire à ce type de produit.

Mahamoud Saïd Omar

Related Posts

Leave A Comment