Naomi Hauret

Workflow front-end : un nouvel espoir (partie 3)

11 minutes de lecture

Cet article est le troisième d'une série consacrée à réflexion et la refonte de notre workflow, outils et pratiques front-end. Il présente la première nouvelle version de notre stack, toujours en cours d'amélioration.

TL;DR : npm + Webpack (en 3 fichiers) pour l'automatisation des tâches; Browserslist; PostCSS, CSS Modules, TailwindCSS pour le style; React + Redux; Jest, Enzyme, Loki pour les tests; Storybook pour le styleguide et la doc front-end.

developpeurs-nouvelle-stack-front-illustration.jpg

<div align="center">Développeurs et leur nouvelle stack front dansant sur le corps de l'ancienne stack - illustration</div><br>

L'An de Grâce 2018 vers à peu près 1h du matin...

<br>

C'est le souffle court et les doigts fébriles que je pianote sur mon clavier les quelques instructions suivantes :

<br>

git add .

git commit -m ":tada: :sparkles: first commit"

git push

<br>

La destination de ce commit énigmatique ? Un repo sobrement nommé frontkit-react-redux sur notre Gitlab.

Son contenu ? Un premier jet de notre nouvelle stack front. Vous avez pu suivre, non sans passion, les réflexions que nous avons pu avoir sur le statut de nos pratiques, outils et workflow.

C'est donc sans surprise que nous allons vous dévoiler nos premiers travaux sur la refonte de notre workflow et de notre stack front-end.

<br>

Automatisation des tâches

<br>

Babel

<br>

Pour transpiler notre Javascript ES6+ en ES5 lisible et compréhensible par tous les navigateurs que nous ciblons, notre choix s'est porté sur BabelOuvre une nouvelle fenêtre.

Notre config utilise le traditionnel preset env qui, combiné à la config de browserslist, nous permet d'appliquer les transformations et polyfills nécessaires aux navigateurs ne supportant pas certaines features ES6/ES7. Au vu de notre choix technologique (spoiler: React), nous utilisons aussi le preset react ainsi que le plugin transform-react-inline-element, pour améliorer la rapidité avec laquelle nos composants s'affichent ainsi que react-remove-prop-types, un plugin qui comme son nom l'indique, retire les prop-types (nous l'appliquons en environnement de production).

<br>

Webpack

<br>

Afin d'avoir entièrement la main sur notre workflow, nous avons décidé d'utiliser le plus célèbre des bundlers : WebpackOuvre une nouvelle fenêtre.

Nous avons découpé notre workflow en 3 fichiers de config :

.dev

<br>
  • Création d'un serveur pour notre application, accessible depuis tout appareil utilisant le même réseau
  • Hot Module Replacement, pour le JS et le CSS (parce que recharger la page, c'est nul)
  • Création de sourcemaps, pour faciliter le débuggage
<br>

.prod

<br>
  • Purification du Javascript (retrait du code mort, minification)
  • Création des chunks (modules Javascript utilisés par plusieurs points d'entrée et leurs enfants)
  • Minification du HTML
  • Purification du CSS (retrait des styles non appliqués, minification)
  • Injection du CSS critique dans le HTML
<br>

.common, pour les tâches communes aux 2 environnements précédemment cités :

<br>
  • Transpilage avec Babel
  • Extraction des styles (CSS-Modules et CSS classique) dans un fichier .css, application des plugins PostCSS (import, Tailwind, CSSNext)
  • Injection des bundles CSS et JS et des vendors de façon automatique dans un template HTML (les bundles ont un nom hashé)
<br>

Améliorations en cours et à venir

<br>
  • Amélioration des performances (vitesse d'exécution, taille des bundles générés), une bataille de chaque jour
  • Mise en place du code splitting, pour gagner en rapidité
  • Passage à Webpack 4Ouvre une nouvelle fenêtre, qui ne se fera que quand tous les plugins que nous utilisons dans nos fichiers de configuration qui ne sont pas inclus dans cette nouvelle version 4 soit v4 friendlyOuvre une nouvelle fenêtre.
<br>

Côté application client

<br>

React

<br>

La plupart de l'équipe ayant pu se faire une petite expérience sur ReactOuvre une nouvelle fenêtre, nous nous sommes pour l'instant positionné sur la célèbre librairie de Facebook pour construire nos applications.

<br>

Les améliorations à venir

<br>

Mise en place de l'environnement Redux

<br>

Comme pour React, ce premier jet de stack pioche sur un outil sur lequel l'équipe a pu se faire la main pour nos futures applications nécessitant un state manager : ReduxOuvre une nouvelle fenêtre.

Nous pensons mettre en place l'architecture DucksOuvre une nouvelle fenêtre pour organiser la logique de nos composants.

<br>

Animations, transitions et micro-interactions

<br>

Un des souhaits communs aux pôles design, développement front et développement back, c'est la mise en place d'animations, de transitions entre les pages et de micro-interactions afin de créer des sites plus dynamiques.

CSS nous permet déjà de faire des choses formidables, mais voici quelques outils auxquels nous aimerions jeter un coup d'oeil :

<br><br>

Côté Style

<br>

Il s'agit de l'une des parties de notre stack qui a le plus radicalement changé. Pour rappel, nous utilisons, sur nos projets historiques, Sass (LESS pour les projets les plus anciens) avec Boostrap (3 ou 4 selon la date de naissance de projet) sur une architecture 7-1Ouvre une nouvelle fenêtre, PostCSS pour certains cas et Trowel en supplément (ou Silverhold, la version dépréciée de Trowel).

<br>

Pour la nouvelle stack, nous avons choisi d'utiliser du CSS tout simple augmenté avec PostCSS (avec les modules CSSNext, qui inclut AutoprefixerOuvre une nouvelle fenêtre pour préfixer nos styles selon les navigateurs que nous supportons, et easy-importOuvre une nouvelle fenêtre pour le moment).

La plupart de nos styles sont générés par TailwindCSSOuvre une nouvelle fenêtre, qui nous permet de gérer automatiquement toutes les classes atomiques dont nous avons besoin pour créer de superbes interfaces.

Pour les styles plus complexes ou les animations, nous avons choisi d'essayer les CSS-Modules.

<br>

Documentation

<br>

Storybook

<br>

Coutumier de l'approche Atomic Design et des styleguides, la nouvelle stack a vu l'arrivée de StorybookOuvre une nouvelle fenêtre, une solution qui permet de tester ses composants visuels dans un environnement isolé de notre application.

Grâce à une combinaison d'addons, nous pouvons, en plus d'avoir un styleguide, générer une documentation pour nos composants et tester leur accessibilité (dans une certaine mesure).

<br>

Tests

<br>

Jest + Enzyme

<br>

Une envie que nous avions depuis quelques temps, c'est la création de tests côté front-end. Pour cela, nous avons choisi le framework JestOuvre une nouvelle fenêtre, créé par Facebook, et l'utilitaire EnzymeOuvre une nouvelle fenêtre de Airbnb. Nous écrivons donc des tests unitaires pour chacun de nos composants visuels (retrouvez ici une explication (en anglais)Ouvre une nouvelle fenêtre sur les différences entre tests unitaires, tests fonctionnels et tests d'intégration).

<br>

Ensemble, ces outils se révèlent diablement efficaces et permettent de tester la structure des composants en comparant un snapshot (une photo) de la structure initiale d'un composant avec un nouveau snapshot qui lui est présenté.

En plus de la structure, ces outils permettent également de tester l'interactivité d'un composant (quand je clique/sélectionne/survole/change quelque chose, est ce qu'il se passe bien quelque chose ?).

<br>

Améliorations en cours et à venir

<br>

Nous souhaitons mettre en place des tests de régression visuelle. Quelques solutions existent pour mener à bien cette tâche. Nous avons décidé de tenter le coup avec un outil nommé LokiOuvre une nouvelle fenêtre. A voir ce que cela va donner !

<br>

Linter et formatter

<br>

Nous avons choisi PrettierOuvre une nouvelle fenêtre pour formater notre code et ESLintOuvre une nouvelle fenêtre ainsi que StylelintOuvre une nouvelle fenêtre pour linter le Javascript et le CSS/PostCSS (respectivement).

ESLint est configuré pour suivre les standards d'écriture de React et nous alerter en cas de non respect des normes d'accessibilité dans le markup de nos composants.

Stylelint, quant à lui, nous avertit si nous utilisons des unités autres que les rem et les em (en plus des règles d'écriture standards).

<br>

Git Hooks avec Husky et lint-staged

<br>

Les Git Hooks sont des scripts et instructions qui sont exécutés avant qu'un commit ou qu'un push ne soit lancés et dont la bonne exécution permet ce commit ou ce push.

Pour ces tâches, nous avons choisi HuskyOuvre une nouvelle fenêtre, en combinaison avec lint-stagedOuvre une nouvelle fenêtre.

<br>

Avant chaque commit, nous lançons sur les fichiers dont les modifications ont été enregistrées dans le dépôt git (en gros où on a fait git add), le formatage et le lintage puis nous lançons les tests (si ces composants en ont).

Cette approche permet d'éviter de réévaluer l'ensemble de la code base : si 5 fichiers / 250 ont été modifiés, pourquoi réévaluer les 245 autres sachant que seul du code propre peut être commit et push sur l'index de notre repo ?

<br>

git-hook-preserve-qualite-code-illustration.jpg

<div align="center">Développeurs et leur nouvelle stack front dansant sur le corps de l'ancienne stack - illustration</div><br>

Architecture

<br>

Voici l'architecture à laquelle nous arrivons avec cette stack :

<br>

Avant

<br>
1├── .babelrc
2├── .bowerrc
3├── .scss-lint.yml
4├── gulpfile.babel.js
5├── bower.json
6├── composer.json
7├── composer.lock
8├── package-lock.json
9├── package.json
10├── yarn.lock
1112├── app
13│   ├── config
14│   │   ├── webpack.config.js
15│   │   └── maba_webpack.yml
16│   └── Resources
17│       └── views
18│           ├── page
19│           │   ├── < Some Page >
20│           ├── styleguide
21│           │   ├── components
22│           │   └── ui
23│           └── svg
24└── src
25    └── AppBundle
262728        └── Resources
29            ├── public
30            │   ├── fonts  
31            │   ├── images
32            │   └── styleguide
3334            ├── script
35            │   ├── <Some Component>
36            │   │   ├── components
37            │   │   │   ├── containers
38            │   │   │   └── presentational
39            │   │   └── utils
40            │   ├── components
41            │   └── polyfill
42            └── style
43                ├── bases
44                ├── components
45                ├── layouts
46                ├── pages
47                ├── utils
48                ── vendors
49                    └── bootstrap
50                        ├── rewrites
51                        └── utils
<br>

Après

<br>
1├── .babelrc
2├── .eslintrc
3├── .gitignore
4├── .prettierrc
5├── .stylelintrc
6├── jest.setup.js
7├── package.json
8├── package-lock.json
9├── postcss.config.js
10├── README.md
11├── src
12│   ├── assets
13│   │   ├── css
14│   │   │   └── main.css
15│   │   ├── fonts
16│   │   └── img
17│   ├── components
18│   │   ├── containers
19│   │   │   └── App.js
20│   │   └── presentationals
21│   │       └── <Example Component>
22│   │           ├── index.js
23│   │           ├── index.stories.js
24│   │           ├── index.test.js
25│   │           ├── __snapshots__
26│   │           │   └── index.test.js.snap
27│   │           └── styles.css
28│   ├── index.html
29│   ├── index.js
30│   └── pages
31├── .storybook
32│   ├── addons.js
33│   ├── config.js
34│   └── webpack.config.js
35├── tailwind.js
36├── webpack.common.js
37├── webpack.dev.js
38└── webpack.prod.js
<br>

Contrairement à notre ancienne architecture, ici le front est totalement séparé du back. Nous suivons le principe suivant : chaque composant doit pouvoir fonctionner et être testé de façon indépendante, d'où l'architecture de composant suivante :

<br>
  • index.js : la définition du composant
  • index.stories.js : les stories du composant, c'est-à-dire la liste de ses différents états visuels (les .stories sont ce qu'utilisent storybook)
  • index.test.js : définition des tests du composant
<br>

Retour d'expérience sur ces premiers travaux

<br>

Refondre sa stack front ne se fait pas du jour au lendemain et dans son coin ! Principale actrice du passage de la stack front historique à cet embryon, j'ai voulu rapprocher les différents pôles de l'agence :

  • design
  • back
  • SEO/stratégie média
<br>

Le développement front-end est en effet le pont qui va relier ces différents points entre eux : le code se doit de donner vie aux maquettes en étant plus qu'un simple miroir statique par des micro-interactions et des animations. Il doit également leur implémenter un système nerveux en reliant l'interface à la logique back-end. Mais à quoi sert de faire un site si personne ne le voit ? Le SEO a également toute sa place si l'on cherche à réécrire sa stack et son workflow.

<br>

C'est dans ce but que la discussion de cette refonte s'est effectuée sur notre Discourse et lors de discussions informelles, afin que chacun puisse expliquer ses problèmes, frustrations et attentes sur la stack front : l'occasion pour chacun donc, d'apporter sa pierre à l'édifice, même pour les non-développeurs.

<br>

Pour ma part, cela m'a permis de tester des technologies et des combinaisons que je n'avais jamais encore pu croiser dans le vaste monde front-end (les CSS Modules avec un framework CSS atomique, certaines combinaisons d'addons dans Storybook), d'en découvrir certaines (Jest, Enzyme et Loki) et, plus important, d'en approfondir d'autres, surtout la configuration de Webpack pour un environnement de production.

<br>

Car c'est surtout là que repose la difficulté de l'exercice : savoir comment configurer et lier les outils que l'on utilise entre eux. C'est peut-être là le point noir principal de cette expérience : il faut un certain background technique pour tout mettre en place, et assez de pédagogie pour documenter et expliquer le rôle de chaque chose et comment interagir avec, à l'oral comme à l'écrit.

<br>

Mais il reste encore beaucoup à faire, beaucoup à découvrir. Cette stack n'est pas vouée à être figée. Des jumelles alternatives verront certainement le jour (avec InfernoOuvre une nouvelle fenêtre, CerebralOuvre une nouvelle fenêtre ou d'autres technos que l'on jugera bon d'intégrer à notre workflow). L'architecture et les technos bougeront sans doute au fur et à mesure que nous testerons cette stack.

<br>

Discutez, renseignez-vous, et surtout documentez et expliquez vos résultats. Car rien ne sert d'avoir un vaisseau capable de transporter tout un monde si vous seul savez comment le conduire.