Migration d'un script Grunt pour npm script

Publié le 10 février 2016 par Victor Darras | front

Cet article est publié sous licence CC BY-NC-SA

Aujourd’hui nous verrons ensemble comment passer un site statique généré avec Grunt en site static généré avec npm script. Je ne souhaite pas ici débattre des bons ou mauvais côté de la chose, c’est un combat qui a déjà été mené sur bien des fronts, dont vous retrouverez la liste en bas de cet article.

Pourquoi faire, me direz-vous ? Après avoir lu ce très bon article sur le sujet dont je vous résumerai les grandes lignes par la suite, j’ai trouvé évident de devoir tester les script npm. Nous allons donc migrer ensemble la génération d’un site statique.

Pour l’exemple j’ai pris un projet simple, avec un template Slim pour le HTML, un fichier Stylus pour les CSS, de la concaténation de JavaScript etc…

Voyons ensemble les tâches principales existante dans le Gruntfile :

  // Run the projet in the browser and watch the file changes
  grunt.registerTask "default", ["browserSync","watch"]

  // Run all the tasks to generate static files
  grunt.registerTask "build", ["slim", "stylus", "concat", 'uglify', "copy"]

  // Connect to a distant diretory (FTP) and upload files
  grunt.registerTask "deploy", ["build", "sftp-deploy"]

Le détail des autres tâches est suffisamment peu complexe pour que j’en passe la description, mais vous pouvez lire le Gruntfile au complet.

L’ensemble des fichiers de sources sont placés dans un dossier /src et seront compilés dans le dossier /build. Nous avons donc une structure de fichier comme ceci :

  • /build
  • /node_modules
  • /src
    • /images
      • favicon.ico
      • victor.jpg
    • /script
      • /vendor
      • script.js
    • index.slim
    • style.styl
    • contact.php
  • Gruntfile.coffee
  • package.json

Installer quel plugin ?

Puisque nous n’utiliserons plus Grunt, il est inutile d’utiliser les plugins relatifs à ce dernier. Nous pouvons utiliser des paquets plus “bas niveau” pour la plupart des tâches. Dans un premier temps je vais effacer le package.json existant ainsi que les node_modules et nous allons initialiser un nouveau projet npm avec npm init.

Actuellement nous utilisons les plugins Grunt suivants :

  • grunt-contrib-watch
  • grunt-slim
  • grunt-contrib-stylus
  • grunt-contrib-uglify
  • grunt-sftp-deploy
  • grunt-contrib-copy
  • grunt-contrib-concat

Que nous remplacerons par les paquets suivants :

  • concat-cli va gérer la concaténation
  • dploy gérera le déploiement
  • minifier minifiera certains fichiers
  • stylus compilera les CSS
  • watch surveillera nos fichiers

Nous allons installer chacun de ces paquets avec la commande suivante :

npm install -g concat-cli dploy minifier stylus watch

Exception à l’utilisation de JavaScript pour l’exercice d’aujourd’hui, nous allons utiliser un peu de Ruby. Installons ensemble Slim pour pouvoir compiler notre page en HTML :

gem install slim # On utilise une gem Ruby

Script npm, ça ressemble à quoi ?

Maintenant que nous avons reconstruit notre boîte à outils (plus légère que l’originale donc), voyons comment configurer son utilisation. Pour ce faire, ouvrons le fichier package.json, où vous devriez voir une ligne scripts par défaut.

Dans un premier temps je vais vérifier que mon dossier /build où se trouveront nos fichiers compilés est bien vide avant compilation. Puisque nous utilisons un script npm plutôt que Grunt nous pouvons directement lancer des commandes shell. Nous allons donc créer une tâche clean qui s’occupera de supprimer tous les fichiers :

"scripts": {
  "clean": "rm -rf ./build/*",
  }

Passons maintenant à toutes les tâches basiques dont nous aurons besoin. On se contentera généralement de passer une liste de fichiers avec quelques arguments à chaque outil. Notons que cette partie est relativement plus complexe qu’avec des plugins Grunt (ou Gulp ou autres) qui ajoutent généralement une couche d’abstraction commune à toutes les tâches. Ici, il sera nécessaire d’aller vérifier chacune des documentations relatives aux paquets utilisés, accessible sur npmjs.com.

Slim (Doc)

Maintenant que le dossier est bien propre, nous pouvons y ajouter le HTML avec Slim. Attention, l’exécutable de Slim s’appelle avec la commande slimrb (depuis 0.8.1).

La commande est simple, on utilise slimrb sur le fichier source et on injecte le résultat dans un fichier cible avec >.

"slim": "slimrb ./src/index.slim > ./build/index.html"

Stylus (Doc)

Pour Stylus, même démarche, on définit le fichier à compiler avec -c et le dossier cible avec -o. Un fichier style.min.css sera créé dans le dossier.

"stylus": "stylus -c ./src/style.styl -o ./build/"

Concat-cli (Doc)

Ici nous allons concaténer tous les fichiers JavaScript dont nous aurons besoin. Nous utilisons l’argument -f pour définir quels fichiers nous voulons concaténer et dans quel ordre. Avec -o nous définissons la sortie du fichier.

"concat": "concat-cli -f ./src/scripts/vendor/jquery.js ./src/scripts/vendor/jcanvas.min.js ./src/scripts/vendor/jquery.velocity.min.js ./src/scripts/vendor/velocity.ui.js ./src/scripts/script.js -o ./build/script.js"

Minifier (Doc)

Point important, une convention de npm script est de permettre de définir des pre scripts et des post scripts. Ils seront exécutés avant le script du même nom. Ainsi nous pouvons nous assurer qu’il existe bien un fichier concaténé à minifier :

"preminify" : "npm run concat",
"minify": "minify --output ./build/script.min.js ./build/script.js ",

Quelques scripts pratiques à utiliser

Copy

Pour les besoins de notre site nous aurons besoin des différentes images ainsi qu’un script en .php. Ils sont placés dans src/ mais n’ont besoin d’aucun traitement. Nous allons les copier avec la commande cp. L’argument -R permet de copier récursivement, et -f permettra de forcer le déplacement sans confirmation de notre part.

"copy": "cp -Rf ./src/images/ ./build/images/ && cp -Rf ./src/contact.php ./build/contact.php",

Watch (Doc)

Pour un rythme de travail efficace il vaut mieux se munir d’un watcher qui rechargera une commande lors de la modification d’un ou plusieurs fichiers. La commande se compose de l’appel à watch, de la commande à lancer entre guillemets puis du fichier ou répertoire à surveiller.

"watch": "watch 'npm run build' ./src/",

Build

Maintenant que la plupart de nos tâches sont définies, nous allons les regrouper sous un même script que l’on appellera build. Ensuite nous pouvons lister les appels à chacun des scripts pour les lancer à la suite avec && ou en parallèle avec &.

"build": "npm run clean && npm run slim & npm run stylus & npm run minify & npm run copy",

Deploy (Doc)

Enfin, pour le déploiement de notre site web nous allons transférer les fichiers en sFTP sur le serveur web. Afin de configurer dploy, créons un fichier dploy.yaml à la racine du projet, dans lequel nous allons rentrer les informations suivantes :

server:
  scheme: "sftp"
  host: "sftp.dc0.gpaas.net"
  port: 22
  user: "victor"
  path:
    local: "./build/"
    remote: "/lamp0/web/vhosts/victordarras.fr/htdocs/"

Le path.local correspond à notre dossier de fichiers compilés alors que le path.remote indique où placer les fichiers sur le serveur. Pour toutes les informations liées à la configuration SSH ou autre support de FTP, je vous incite à jeter un œil à la documentation.

Comme nous n’avons qu’un serveur configuré, dploy utilisera celui-ci par défaut. Nous allons lancer la tâche build afin d’être sûr d’avoir le site à jour, puis il nous suffit de lancer dploy :

"deploy": "npm run build && dploy"

Conclusion

Nous avons vu les étapes principales, et je vous incite à jeter un œil aux différentes documentations pour être à l’aise avec l’outil. Nous sommes passés rapidement sur l’utilisation de cpet rm qui sont des commandes bash et donc non disponibles sur Windows. Cet article explique très bien les pièges à éviter et les astuces pour créer des scripts pour n’importe quel OS.

Si vous jetez un œil aux fichiers Gruntfile et package.json présents sur Git, vous remarquerez que nos npm scripts sont bien plus concis et rapides à écrire (de l’ordre de 1 pour 4 environ). À contrario, le .json n’est pas des plus adaptés pour écrire des commandes. Avec une coloration syntaxique limitée et aucune possibilité d’indentation, il reste un langage déclaratif peu lisible dans notre cas. Il est bien sûr possible d’appeler des fichiers externes pour écrire du JavaScript directement.

Le meilleur apport lié à l’utilisation des npm scripts reste que nous utilisons moins de paquets, qu’il sont mis à jour plus rapidement puisqu’ils ne sont plus dépendants de la mise à jour d’une couche d’abstraction. Cette même couche d’abstraction qui, avec Gulp ou Grunt, nous permet de configurer plus rapidement nos outils puisque leurs configurations sont similaires.

J’espère que cet article vous a plu, n’hésitez pas à le partager autour de vous et surtout à poser vos questions en commentaire. Je vous laisse sur quelques ressources externes, en anglais pour la plupart, qui abordent le sujet avec des objectifs ou des démarches différentes.

Links


L’équipe Synbioz.

Libres d’être ensemble.