-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
179 additions
and
0 deletions.
There are no files selected for viewing
179 changes: 179 additions & 0 deletions
179
_posts/2023-09-06-migrer-de-commonjs-vers-esm-migration.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
--- | ||
layout: post | ||
title: "Migrer de CommonJS vers ECMAScript Modules - #2" | ||
date: 2023-09-06 14:04:00 +0200 | ||
categories: javascript | ||
excerpt: "Récit d'une aventure : migrer 400kLoc NodeJs en deux mois - Le faire" | ||
cover: | ||
image: "cjs-to-esm.png" | ||
source_url: https://raw.githubusercontent.com/wessberg/cjstoesm/master/documentation/asset/logo.png | ||
authors: pierre_top | ||
--- | ||
|
||
## Y'a quoi au menu ? | ||
|
||
(Cet article est la suite de [la théorie sur la migration ESM](post_url 2023-08-25-migrer-de-commonjs-vers-esm %}.) | ||
|
||
Il explique enfin comment nous nous y sommes pris pour migrer l'API du monorepo [Pix](https://github.com/1024pix/pix/tree/dev/api). | ||
|
||
Si vous n'avez que cinq minutes, lisez [la stratégie](#la-stratégie). | ||
|
||
Si vous avez un peu plus de temps, choisissez dans le menu. | ||
|
||
Voilà les plats principaux : | ||
- monter et faire vivre [l'équipe dédiée](#léquipe) | ||
- [la stratégie](#la-stratégie) de migration | ||
- faire de la [mise en production](#en-approchant-de-la-production) un non-évènement | ||
|
||
Et si vous êtes gourmands, lisez tout du début à la fin... | ||
|
||
## L'équipe | ||
|
||
### Traiter les besoins internes | ||
Chez Pix, le développement est effectué par des [Feature Teams]( https://github.com/1024pix/pix-lifestyle/blob/main/organisation/equipes.md) (FT), qui reçoivent les besoins utilisateurs principalement par le Product Owner (PO). Les développeurs peuvent participer au recueil et au raffinement du besoin, et le questionner lors de l'implémentation (le détail est expliqué [ici](https://m.youtube.com/watch?v=r0VmGhjnJr4)). | ||
|
||
Les besoins d'amélioration interne au pôle engineering, dont fait partie la migration ESM, suivent un processus particulier, appellé "Impact Team". Des développeurs sont détachés de leur équipe pour un temps défini, en général quelques semaines, avec un objectif clair, même si le sujet est exploratoire. | ||
|
||
Pour la migration ESM, un développeur a fait une présentation de 15 minutes à tous les autres développeurs, en exposant le besoin et la solution qu'il proposait. Il a ensuite proposé qu'un autre développeur, volontaire, le rejoigne pour deux semaines afin de réaliser la migration. | ||
|
||
### Travailler ensemble | ||
|
||
La taille de l'équipe est importante : elle a permis de combiner les connaissances et les absences ponctuelles ; autrement dit, elle évitait les dépendances. Il y avait bien sûr un [surcoût](#coût-de-coordination-et-complexité) par rapport à confier le travail à une seule personne, mais la complexité du sujet était trop grande. | ||
|
||
Le développement, dès le début, s'est fait en pair programming, en rotations de 30 minutes, la plupart du temps en présentiel. Le pair programming est [encouragé chez Pix]( https://github.com/1024pix/pix-lifestyle/blob/main/pratiques/pair-et-mob-programming.md ) et il a été crucial ici : répartir la connaissance, trouver les solutions et se soutenir lorsqu'il fallait effectuer des corrections manuelles. | ||
|
||
Les corrections manuelles ont aussi été faites en pair programming, même si on pense spontanément à paralléliser les tâches répétitives. En effet, la personne qui ne code pas, pendant que son partenaire modifie les fichiers : | ||
- signale les erreurs d'inattention ; | ||
- pense aux cas qui ne sont pas couverts ; | ||
- suggère de meilleurs moyens d'effectuer la correction (ex: grouper les fichiers) ; | ||
- prend du recul sur ce qui se passe. | ||
|
||
Être deux nous a permis de prendre soin l'un de l'autre et de mener à bien la migration ; seuls, nous n'aurions pas reconnu la fatigue et aurions persisté dans des solutions qui étaient des impasses. Mon ressenti est qu'il a été plus facile de prendre soin de l'autre que de moi-même, et que l'autre me rappelait quand je ne prenais pas soin de moi. | ||
|
||
En plus de cette boucle de feedback de 30 minutes, il y en avait une aure boucle quotidienne. La journée commençait avec un partage de 15 minutes de l'avancée avec les CTO, sur la base d'un résumé fait en fin de journée sur le Wiki interne. Cela permettait à l'équipe de prendre du recul sur ce qui s'était passé, et aux CTO d'envisager des actions pour enlever des obstacles : suggérer des expérimentations, demander de l'aide aux autres équipes. | ||
|
||
Ce partage quotidien a assuré la confiance. Lorsque les deux semaines initialement imparties étaient écoulées, les CTO ont décidé que la migration pouvait être poursuivie, sachant que nous traitions les risques les plus importants en premier. Si la migration s'avérait impossible, ils le sauraient rapidement et pourraient décider d'arrêter le chantier. | ||
|
||
Ne gardons pas le suspense plus longtemps, d'autant que la présentation de l'article le mentionne : la migration a pris deux mois au lieu des 2 semaines annoncées ([ce qui était prévisible après tout](#estimation])). | ||
|
||
|
||
## La stratégie | ||
|
||
Parler de stratégie n'est pas tout à fait honnête, car nous n'avions pas de plan, uniquement quelques principes. | ||
Nous partageons ici notre expérience pour vous aider à en avoir une si vous vous lancez dans l'aventure. | ||
|
||
### Un feedback rapide | ||
Nous n'avons envisagé la migration que parce que nous avions des tests automatisés avec une bonne couverture. | ||
|
||
La démarche classique de refactoring (car c'en est un) aurait été de migrer un fichier (SUT) en ESM et de vérifier que le test passe toujours. Le test (CJS) importerait le SUT (ESM), qui lui-même importerait des dépendances (ESM). | ||
Pour cela, il faudrait que ESM et CJS soient interopérables, et bien que le sujet commence à être [implémenté et documenté](https://github.com/johnloy/esm-commonjs-interop-manual#tooling), l'investissement ne semblait pas être un bon compromis. | ||
|
||
Nous pensions procéder en trois étapes : | ||
- migrer l'implémentation et effectuer un test manuel, à savoir démarrer l'API ; | ||
- exécuter [les tests automatisés de bout en bout (front + back)](https://github.com/1024pix/pix/tree/dev/high-level-tests/e2e) ; | ||
- migrer les tests automatisés de l'API puis les exécuter. | ||
|
||
La conséquence était la suivante : pendant la première partie, nous n'avions plus aucun test qui nous couvrait. | ||
Autrement dit : nous avons modifié la moitié de la codebase sans savoir si nos modifications étaient correctes. Même la vérification statique (lint) n'a pas fonctionné tout de suite, car un fichier dont le code est invalide ne peut être parsé. Les modifications étant effectuées par des codemods et des modifications manuelles, si elles se révélaient incorrectes et qu'il fallait les rejouer, nous n'étions pas à l'abri de devoir refaire ces actions manuelles. | ||
|
||
Au fur et à mesure que les deux semaines se sont allongées, nous ressentions de plus en plus le poids d'une épée de Damoclès. À la prochaine migration de codebase, il serait judicieux de remettre en cause cette stratégie ! | ||
|
||
Nous avons découvert en cours de route une solution intermédiaire pour retrouver du feedback rapide : remplacer certaines fonctionnalités CJS difficiles à migrer en ESM par d'autres fonctionnalités CJS, elles-mêmes faciles à migrer. On profite ainsi des tests automatisés en développement et de l'utilisation en production. | ||
|
||
### Choisir ses combats | ||
|
||
On ne pouvait pas gérer toute la syntaxe, on a écrit les codemods obligatoires | ||
Le reste est modifié manuellement. Ce n'est pas un échec. | ||
|
||
|
||
Cela aboutit, après plusieurs tentatives, à ce ![workflow de développement](/assets/images/posts/migrer-de-commonjs-vers-esm-migration/codemod-workflow.png) | ||
|
||
"Codemodception" | ||
|
||
CJS=>CJS | ||
https://github.com/1024pix/pix/pull/5715 | ||
https://github.com/1024pix/pix/pull/5747 | ||
|
||
|
||
### Le choix des exports nommés | ||
|
||
Sondage dans les équipes | ||
|
||
Exception : les fichiers qui n'exportent qu'un seul objet (use-case) | ||
https://github.com/1024pix/pix/pull/5787/files#diff-734269ab23f38145d1f6742bd4282022dc6d47a8f57c3e2b372e45da7f1d88f4 | ||
|
||
|
||
|
||
Ou alors on transforme les exports anonymes CSJ en exports nommés CJS (et les imports aussi). | ||
|
||
Ca permet de lancer les tests en CJS donc d’aller plus vite. | ||
|
||
Et du coup il reste plus que deux codemods CJS=>ESM qui ne gèrent que les imports/exports nommés (simples!). | ||
|
||
générer un import nommé ESM (on part du principe que le nom de la variable est prévisible, c’est le nom du fichier snake-case transformé en camelCase/PascalCase) | ||
|
||
https://github.com/1024pix/pix/pull/5731 | ||
|
||
### Les tests mockés et l'injection de dépendance | ||
|
||
|
||
## En approchant de la production | ||
|
||
### Le suivi et la motivation | ||
L'équipe de production a affiché l'avancée de la migration sur [Are we ESM yet ?](https://1024pix.github.io/areweesmyet/). | ||
|
||
C'est une [Github page](https://github.com/1024pix/areweesmyet) avec un appel à l'API de la CI qui affiche l'avancement des tests, simple, mais efficace. Elle rend le travail et les difficultés visibles à tous. | ||
|
||
![dashboard code](/assets/images/posts/migrer-de-commonjs-vers-esm-migration/are-we-esm-yet.png) | ||
|
||
### Comment tester hors CI ? | ||
|
||
https://1024pix.atlassian.net/wiki/spaces/TC1/pages/3754164240/D+ploiement+de+l+API+en+ESM | ||
|
||
On s'est posé la question un peu tard, brainstorming avec les [captains](/organisation/2020/04/14/les-capitaines-de-la-production.html) | ||
|
||
Parler du canary | ||
https://github.com/1024pix/pix-dev-tools/tree/main/captain/canary-releases | ||
https://github.com/1024pix/pix/blob/dev/mon-pix/servers.conf.erb#L30 | ||
|
||
Modification du workflow Slack | ||
![dashboard canary](/assets/images/posts/migrer-de-commonjs-vers-esm-migration/canary.png) | ||
|
||
2 semaines de déploiement progressif: front, workers.. | ||
|
||
|
||
## Happy end | ||
|
||
Le 1er juin 2023, 3 mois après avoir donné le coup d'envoi, toute la production tourne en ESM | ||
https://1024pix.github.io/areweesmyet/ | ||
|
||
![dashboard code](/assets/images/posts/migrer-de-commonjs-vers-esm-migration/are-we-esm-yet.png) | ||
|
||
## Plus | ||
|
||
### Le code | ||
La [pull request principale](https://github.com/1024pix/pix/pull/5787) et ses 132 commits | ||
Zoom sur les codemods | ||
|
||
### Workflow canary | ||
Voilà la stratégie de déploiement | ||
![workflow canary](/assets/images/posts/migrer-de-commonjs-vers-esm-migration/workflow-canary.png) | ||
|
||
### Coût de coordination et complexité | ||
|
||
Un problème qui ne peut être résolu seul demande de la coordination, qui a un coût. | ||
|
||
> In tasks that can be partitioned but which require communication among the subtasks, the effort of communication must be added to the amount of work to be done. The added burden of communication is made up of two parts, training and intercommunication. Each worker must be trained in the technology, the goals of the effort, the overall strategy, and the plan of work. This training cannot be partitioned, so this part of the added effort varies linearly with the number of workers. Intercommunication is worse. If each part of the task must be separately coordinated with each other part, the effort increases as n(n-1)/2. Three workers require three times as much pairwise intercommunication as two; four require six times as much as two. | ||
> If, moreover, there need to be conferences among three, four, etc., workers to resolve things jointly, matters get worse yet. The added effort of communicating may fully counteract the division of the original task | ||
in Fred Brooks, The mythical man-month, Chapter "The Man-month", page 18 | ||
|
||
### Estimation | ||
|
||
L'informatique n'est plus si jeune, les développeurs non plus, et pourtant cette constatation reste la même qu'en 1975. | ||
|
||
> All programmers are optimists. Perhaps this modern sorcery especially attracts those who believe in happy endings and fairy godmothers. Perhaps the hundreds of nitty frustrations drive away all but those who habitually focus on the end goal. Perhaps it is merely that computers are young, programmers are younger, and the young are always optimists. But however the selection process works, the result is indisputable: 'This time it will surely run,'' or "I just found the last bug." | ||
> So the first false assumption that underlies the scheduling of systems programming is that all will go well, i.e., that each task will take only as long as it "ought" to take. | ||
in Fred Brooks, The mythical man-month, Chapter "Optimism", page 15 |
Binary file added
BIN
+312 KB
assets/images/posts/migrer-de-commonjs-vers-esm-migration/are-we-esm-yet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+207 KB
assets/images/posts/migrer-de-commonjs-vers-esm-migration/codemod-workflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+5.99 KB
assets/images/posts/migrer-de-commonjs-vers-esm-migration/the-end.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+326 KB
assets/images/posts/migrer-de-commonjs-vers-esm-migration/workflow-canary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.