Grunt Watch - L'oeil qui voit tout !

dim. 09 mars 2014

Un outil de build comme les autres !

Grunt vous connaissez ? Pour les amateurs de Javascript, Grunt est un outils de build JS, une sorte d'équivalent local à Ant. Pour les autres,... Il s'agit peut-être d'un ouvrier Orc dans l'excellent Warcraft ;)

Logo GruntJs

Mais pourquoi un outil de build JS ? Le javascript, c'est de l'interprété non ? Alors pour tout dire, j'aurai du dire un outil de build Web. En règle général, Grunt va se charger de minifier les fichiers js et css, de lancer les tests unitaires, ... On peut également s'en servir pour lancer les code-checker. Bref, hormis l'étapes de compilation que l'on oublie, l'utilité est la même que celle de tout autre outils de cette catégorie !

Et que vient faire l'Oeil ici ?

Pour moi, l'un des gros autouts de Grunt est les nombreux plugins que l'on peut trouver de part le Web, et l'un d'eux particulièrement : grunt-contrib-watch ! Watch, c'est un utilitaire à qui vous pouvez confier la surveillance de fichiers particuliers. Quand ces fichiers sont modifié, Grunt peut alors déclencher une série d'action. Des exemples ?

Ok... Imaginons que vous travaillez avec un pré-processeur CSS tel que LESS. En développement, vous avez envie de modifier votre fichier less et de visualiser de suite le résultat. Ici, vous pourriez dire à Grunt de surveiller tous les fichiers portant cette extension, et de regénérer les css à la moindre modification. Mieux encore, grâce à LiveReload, vous pourriez même demander à votre navigateur de se rafraichir tout seul !

Donc je résume : on modifie notre code, on sauvegarde, et hop ! Welcome les modications sur la navigateur, sans faire d'action supplémentaire ! A moi la productivité ! Mouhahahahahaha... Hum, pardon :)

Pour les JS... Mais pas que !

Je vous l'avais dit qu'en ce moment je faisait du Php ? Et bien, figurez-vous que la communauté Grunt à crée quelque plugins permettant d'intégré du php ! Deux d'entre eux m'intéresse particulièrement : grunt-phpunit, pour lancer les tests unitaires, et grunt-lint, pour valider la syntaxe du code.

Maintenant, couplez cela à Watch et nous obtenons un système qui a la moindre sauvegarde relance tous... Plus qu'à garder un oeil sur la console et repéré quand un test plante ! Ah, mais attendez, on ne peut pas faire mieux qu'un message console ?

La tâche est morte, vive la tâche !

Euh, je crois que je craque sur les titres là... Bon passons et rajoutons un petit plugin dans notre build : grunt-notify ! Ce petit plugin tout simple va surveiller notre tâche grunt et créer une notification système en cas d'erreur.

Ainsi, si je reprend mon workflow de tout à l'heure :

  • Je code tranquillement en Php.
  • Je sauvegarde.
  • Les tests s'exécutent en tâche de fond, je ne m'en occupe pas.
  • Et hop, un test plante => une petite notification windows apparait.

Je ne sais pas pour vous, mais c'est un process qui me plait ! :)

Et un exemple concret

Bon concrètement, à quoi ressemble mon gruntfile pour gérer ce cas ? Voilà un petit exemple, loin d'être complet il est déjà fonctionnel.

   /**
   * Gruntfile.js
   */
  module.exports = function(grunt) {
    grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    notify_hooks: {
        options: {
            enabled: true,
            max_jshint_notifications: 10,
            title: "Symfony"
        }
    },
    phplint: {
        options: {
            swapPath: ".grunt/lint/"
        },
          all: ['src/Cgi/Bundles/**/*.php']
      },
      phpunit: {
          unit: {
              dir: 'src/Cgi/Bundles/BlogBundle/Tests/Tools/'
          },
          options: {
              bin: 'bin/phpunit',
              colors: true,
              testdox: true
          }
      },
    watch: {
        all: {
            files: ['src/**/*.php'],
            tasks: ['precommit']
        }
    }
    });

    grunt.loadNpmTasks('grunt-php');
    grunt.loadNpmTasks('grunt-phplint');
    grunt.loadNpmTasks('grunt-phpunit');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-notify');
    grunt.registerTask('precommit', ['phplint:all', 'phpunit:unit']);
    grunt.registerTask('survey', ['notify_hooks', 'watch:all']);
  };