PHP a été mon langage favori pendant presque 10 ans. Ruby l’a suivi pour à peu près la même durée. Javascript a été l’outil secondaire pas très attirant pour quand il n’y a pas d’autre choix, c’est à dire sur navigateur.
Avant-hier j’ai eu un petit pincement de frustration en cherchant à déstructurer un dictionnaire lors d’une affectation. Ruby n’a toujours qu’une demie solution pas très élégante. PHP et Javascript ont tous deux énormément évolué entre temps, au point qu’on ne les reconnait qu’à peine.
Si Ruby garde des capacités inégalées pour faire de la méta-programmation, 10 ans c’est peut être le bon moment pour reprendre un autre langage de zéro.
Je fais du web, j’aime beaucoup l’idée de l’isomorphisme, il me faudra donc quelque chose qui sache compiler en Javascript. Elm pourrait me faire du pied vu sa gestion des types mais c’est un pari osé considérant qu’il est encore absent côté serveur.
Ça sera donc Javascript. D’abord pour quelques scripts en ligne de commande, puis peut-être des applications plus sérieuses.
Reprendre de zéro c’est l’occasion de laisser le passé derrière soi et recommencer comme si c’était un nouveau langage. Je ne prends que les dernières versions et outils récents dans la chaîne, voire ce qui n’est pas encore sec mais qui arrivera demain.
Il s’agit aussi de reprendre de zéro, pour apprendre. Exit donc les boiler plate et autres kits de démarrage rapide.
Première étape : installation de npm (3.10.3) et nodejs (6.3.1).
# Sur Mac avec Homebrew (http://brew.sh/) brew install nodejs
et initialisation du projet (un peu de doc si besoin pour aider à remplir)
mkdir my-js-project cd my-js-project npm init
Ensuite l’idée c’est d’utiliser le nouveau Javascript moderne et ne chercher aucune compatibilité passée. Installation de Babel pour gérer ES2015 et + :
npm install --save-dev babel-cli
La plupart des sites recommandent des preset pour ES2015 ou React mais visiblement Nodejs 6.x gère déjà l’essentiel des fonctions nativement. Il existe au moins trois preset spécifiques pour Nodejs 6 mais la seule configuration commune aux trois est le plugin qui transforme les modules ES2015 en modules Commonjs. Je suis donc reparti de là :
npm install --save-dev babel-plugin-transform-es2015-modules-commonjs
Puis l’édition du .babelrc :
{ "presets": [ ], "plugins": [ "transform-es2015-modules-commonjs" ] }
Si quelque chose manque à Nodejs 6, il faudra que j’ajoute le plugin correspondant. Voici les plugins sur lesquels mes trois presets étaient en désaccord :
- transform-es2015-function-name,
- syntax-trailing-function-commas,
- transform-es2015-destructuring,
- transform-es2015-parameters,
- transform-object-rest-spread,
- transform-es2015-sticky-regex,
- transform-es2015-unicode-regex,
- transform-es2015-modules-commonjs,
- et transform-class-properties.
Je n’ai pas pris le temps de les tester un par un pour voir lesquels étaient réellement nécessaires pour pas. Si quelqu’un a le courage de faire le travail…
Reste à enfin permettre d’exécuter un premier script. J’ai tenté de suivre les usages en mettant les sources dans src/ et les fichiers compilés dans lib/ avec un index.js comme fichier principal.
mkdir lib echo "Compiled files will go here." > lib/README.md echo "Leave these files untouched" >> lib/README.md echo "and modify ../src/* instead." >> lib/README.md mkdir src echo "Source files will go here." > src/README.md echo "They should be compiled before any use." >> src/README.md touch src/index.js
Et la configuration du package.json pour lancer tout ça (notez le main qui prend en compte notre nouveau chemin et le scripts qui liste nos deux nouvelles actions) :
{ "name": "my-project", "main": "./lib/index.js", "scripts": { "build": "babel src -d lib --source-maps", "watch": "babel src -d lib --watch --source-maps" }, "devDependencies": { "babel-cli": "^6.11.4", "babel-plugin-transform-es2015-modules-commonjs": "^6.11.5" } }
Un npm run build permet de compiler tous les fichiers, un npm run watch permet de surveiller en temps réel les modifications des fichiers sources pour mettre à jour les fichiers destination correspondants.
J’ai ajouté un README, le .gitignore proposé par Github pour un projet Nodejs, une licence, et ‘op, vous trouverez le tout sur Github.
Ça fait déjà pas mal pour toujours aucune ligne de Javascript utile.
Quelques feedback après ce tout petit premier pas :
1– C’est long et complexe
Oui, j’ai cherché les ennuis, il existe des boiler plate tout faits, mais je ne crois pas avoir le même problème avec Python, Ruby, PHP ou d’autres.
Le fait d’avoir une étape de compilation avec Babel n’aide pas mais Java pourrait en dire tout autant. Pourquoi n’existe-t-il pas un babel init qui lit la version courante de Nodejs, m’installe un .babelrc adapté à cette version et me modifie mon package.json pour m’ajouter les raccourcis build et watch ?
Oui, je pourrais faire une pull-request, mais fallait-il m’attendre ?
2– La doc aide peu
Franchement c’est la plaie. Je ne dirais pas qu’il n’y a aucune doc, mais il y en a dans tous les sens. La plupart ne sont pas à jour, toutes semblent incomplètes, et il est bien difficile de savoir si telle ou telle a pris en compte les dernières évolutions.
Peut-être n’ai-je pas trouvé la bonne référence ? Dites-moi.
Rien que le npm init n’était indiqué sur aucune doc que j’ai croisé. Pire : si on l’oublie il n’y a pas de message rouge très explicite pour indiquer que les npm install –save-dev n’auront pas l’effet demandé. Il a fallu comprendre qu’il fallait créer un package.json, puis découvrir qu’il n’était pas nécessaire de le faire à la main.
Ce n’est que le début. Quand il va s’agir de choisir une bibliothèque ou des outils, je sens que ça va être toute une histoire pour d’y retrouver. La doc de setup de Babel en donne un premier aperçu.
J’ai l’impression qu’à chaque étape la roue est en pleine reconstruction, et qu’on en a fait plusieurs versions différentes en parallèle, pour tout.
3– Qui a eu l’idée d’utiliser des fichiers de config JSON ?
Je suis aussi assez peu fana aussi des config dans des fichiers Json. J’ai l’impression de retrouver les fichiers de configuration XML de Java. Je n’ai pas l’impression que ce soit beaucoup plus lisible.
La grosse différence c’est que Java a créé ces configurations avec tout un outillage autour. Le développeur n’avait que rarement besoin d’y plonger manuellement. C’était géré automatiquement par les IDE et les scripts.
J’ai ajouté un plugin au .babelrc décrit plus haut. Ce plugin a une option. Je me retrouve avec un Json de 7 lignes dont 4 qui contiennent autre chose que des crochets et accolades fermantes.… et déjà un dictionnaire dans un tableau dans un tableau dans un dictionnaire. Rien que ça.
Même mon petit package.json me parait délicat à manipuler malgré l’indentation. Heureusement que les dépendances sont ajoutées automatiquement par npm lors de leur installation.
Là, dès qu’on dépasse le simple clef valeur, j’ai l’impression de me retrouver avec une double peine : Un fichier de configuration peu aisé à manipuler, mais pas pour autant d’outil pour le faire à ma place.
Laisser un commentaire