Depuis quelques temps, le développement de la partie javascript de Stormz était devenu non idéal.
Tout d'abord : le temps de chargement. Nous avions (et nous avons toujours) des centaines de fichiers javascript (frameworks, vues, templates, modèles) qui étaient téléchargés à chaque chargement de page. En développement et pour certaines pages, cela pouvait prendre un peu de temps. Les tests avec guard et teaspoon étaient également très long : plus de 10 secondes après un enregistrement pour avoir un retour.
Deuxièmement, les dépendances. Il était assez difficile de créer un nouveau bundle avec les bonnes dépendances. A la fin, nous copions/collons quelques //= require pour que cela fonctionne.
Cet été a été le moment de changer. Nous voulions désormais utiliser des outils modernes comme npm, les imports es6 et pouvoir intervenir sur la construction de nos bundle facilement. Notre dévolu s'est jeté sur webpack. Un début de migration à la main nous a convaincu que c'était possible assez facilement. Cependant, le nombre de fichiers (source + tests) était trop grand pour ce que soit gérable manuellement. En effet, nous voulions que ce changement pour les utilisateurs ce passe de manière transparente et donc sans régression, mais aussi évitez de maintenir en parallèle une version webpack et une version sprockets ce qui serait rapidement devenu une source d'effort conséquente supplémentaire.
Notre application utilisait un espace de nom global App avec des sous-espaces views, models, routers, etc .... De plus presque tout les fichiers ne contenait qu'un seule définition de classe.
Nous avons donc entrepris d'écrire un migrateur avec recast.
Notre migrateur était par exemple capable de migrer ce type de fichiers :
//= require template/my_view
App.views.MyView = Backbone.View.extend({
render: function() {
this.$el.append(JST['templates/my_view'](_.extend(this.model.toJSON(), {custom: 'value'})));
}
});
En:
import Backbone from "backbone";
import _ from "underscore";
import template from "template/my_view";
export default Backbone.View.extend({
render: function() {
this.$el.append(template(_.extend(this.model.toJSON(), {custom: 'value'})));
}
});
Ce migrateur nous a permis d'avoir confiance dans ce que nous faisions, et nous avions désormais la possiblité de jouer la migration des dizaines de fois pour vérifier que rien n'était cassé.
Nous avons donc intégré ce migrateur dans notre intégration continue. Ensuite nous avons déployé la version webpack pour un nombre restreint d'utilisateurs.
Ainsi nous avons pu corriger quelques soucis et améliorer le déploiement avec l'activation des source-maps.
Grâce à ce système, nous avons ainsi migré l'ensemble de nos utilisateurs vers les assets construits via webpack tout en dormant le soir sur nos deux oreilles.