Naomi Hauret, 25/01/2018

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

12 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.
Illustration de développeurs en joie après la mise en place du nouveau workflow front-end
La jeunesse de Bacchus - William-Adolphe Bouguereau
Développeurs et leur nouvelle stack front dansant sur le corps de l'ancienne stack - illustration

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


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

git add .

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

git push

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.


Automatisation des tâches


Babel


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

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).


Webpack


Afin d'avoir entièrement la main sur notre workflow, nous avons décidé d'utiliser le plus célèbre des bundlers : Webpack.

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

  • .dev
    • 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
  • .prod
    • 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
  • .common, pour les tâches communes aux 2 environnements précédemment cités :
    • 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é)


Améliorations en cours et à venir


  • 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 4, 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 friendly.

Côté application client


React


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


Les améliorations à venir


Mise en place de l'environnement Redux


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 : Redux.

Nous pensons mettre en place l'architecture Ducks pour organiser la logique de nos composants.


Animations, transitions et micro-interactions


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 :


Côté style


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-1, PostCSS pour certains cas et Trowel en supplément (ou Silverhold, la version dépréciée de Trowel).

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

La plupart de nos styles sont générés par TailwindCSS, 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.


Documentation


Storybook


Coutumier de l'approche Atomic Design et des styleguides, la nouvelle stack a vu l'arrivée de Storybook, 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).


Tests


Jest + Enzyme


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 Jest, créé par Facebook, et l'utilitaire Enzyme de Airbnb. Nous écrivons donc des tests unitaires pour chacun de nos composants visuels (retrouvez ici une explication (en anglais) sur les différences entre tests unitaires, tests fonctionnels et tests d'intégration).

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 ?).


Améliorations en cours et à venir


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é Loki. A voir ce que cela va donner !


Linter et formatter


Nous avons choisi Prettier pour formater notre code et ESLint ainsi que Stylelint 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).


Git Hooks avec Husky et lint-staged


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 Husky, en combinaison avec lint-staged.

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 ?

illustration de Git hooks préservant la codebase
Watson and the Shark - John Singleton Copley
Git hook préservant la consistance et la qualité du code de la débâcle - illustration

Architecture


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

Avant :


.
├── .babelrc
├── .bowerrc
├── .scss-lint.yml
├── gulpfile.babel.js
├── bower.json
├── composer.json
├── composer.lock
├── package-lock.json
├── package.json
├── yarn.lock
│
├── app
│   ├── config
│   │   ├── webpack.config.js
│   │   └── maba_webpack.yml
│   └── Resources
│       └── views
│           ├── page
│           │   ├── < Some Page >
│           ├── styleguide
│           │   ├── components
│           │   └── ui
│           └── svg
└── src
    └── AppBundle
        │
        │  
        └── Resources
            ├── public
            │   ├── fonts  
            │   ├── images
            │   └── styleguide
            │
            ├── script
            │   ├── <Some Component>
            │   │   ├── components
            │   │   │   ├── containers
            │   │   │   └── presentational
            │   │   └── utils
            │   ├── components
            │   └── polyfill
            └── style
                ├── bases
                ├── components
                ├── layouts
                ├── pages
                ├── utils
                ── vendors
                    └── bootstrap
                        ├── rewrites
                        └── utils

...

Après :


.
├── .babelrc
├── .eslintrc
├── .gitignore
├── .prettierrc
├── .stylelintrc
├── jest.setup.js
├── package.json
├── package-lock.json
├── postcss.config.js
├── README.md
├── src
│   ├── assets
│   │   ├── css
│   │   │   └── main.css
│   │   ├── fonts
│   │   └── img
│   ├── components
│   │   ├── containers
│   │   │   └── App.js
│   │   └── presentationals
│   │       └── <Example Component>
│   │           ├── index.js
│   │           ├── index.stories.js
│   │           ├── index.test.js
│   │           ├── __snapshots__
│   │           │   └── index.test.js.snap
│   │           └── styles.css
│   ├── index.html
│   ├── index.js
│   └── pages
├── .storybook
│   ├── addons.js
│   ├── config.js
│   └── webpack.config.js
├── tailwind.js
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js

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 :

  • 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

Retour d'expérience sur ces premiers travaux


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

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.

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.

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.

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.

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 Inferno, Cerebral 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.

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.

comments powered by Disqus

Nos derniers articles