GruntJS pour les Nuls !


Technique

GruntJS, c’est quoi ?

« Il était une fois les développeurs front-end qui travaillaient d’arrache-pied sur un projet, puis un autre projet, et d’autres encore. Ces développeurs effectuaient à chaque projet des actions répétitives et rébarbatives pour eux. Ces tâches sont nombreuses, les plus connues étant : devoir minifier les fichiers avant mise en production, réduire le poids des images, concatener le code, etc. »

Si vous êtes développeur front, il est fort probable que ces tâches restent pour vous une perte de temps avec des actions répétées dont chacun se passerait bien. Ce temps est révolu ! Dites bonjour à GruntJS, un outil simple à utiliser et à configurer, nous allons voir comment l’utiliser et comment cet outil vous changera la vie lors de vos développements d’applications front.

Derrière son nom un peu barbare et son taureau, se cache un outil d’exécution de commandes en Javascript. Il possède un large éco-systême de plugins qui vous permettront de faire (sans exagérer) un peu tout et n’importe quoi. Partez du principe que dès que vous faites une action répétée sur un projet, il est fort probable qu’une tâche grunt existe. Sinon, la documentation vous permettra de créer votre propre tâche. Nous allons voir tout cela en détail.

Prérequis et installation

Vous devez avoir préalablement installé Node afin d’utiliser GruntJS. Si ce n’est pas le cas, allez ici et installez Node.
GruntJS s’installe via le gestionnaire de paquets de Node, placez vous en admin dans votre ligne de commande et entrez cette commande :

npm install -g grunt-cli

gruntdemo 0 GruntJS pour les Nuls !

Vous remarquez un ensemble de dépendances installées. Pour commencer à utiliser Grunt, vous devez posséder à la racine de votre projet un fichier package.json contenant la description et les dépendances de votre projet grunt, ainsi qu’un fichier Gruntfile.js.

Commençons par créer le fichier package.json, qui doit posséder ce minimum :

{
"name": "Le nom de votre projet",
"version": "0.1.0",
"devDependencies": {
"grunt": "~0.4.1"
}
}

Remarquez la présence de la première dépendance de notre projet, qui est tout logiquement grunt.

Retournez dans la ligne de commande et tapez :

npm install

Un dossier node_modules est créé et contient (contiendra) touts les packages grunt de votre projet.

Enfin, créez votre Gruntfile.js à la racine du projet. La base d’un fichier grunt est la suivante :

module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

// configuration des tâches grunt

});

// Les tâches sont enregistrées ici
grunt.registerTask('default', []);

};

Vous êtes désormais presque prêt à utiliser Grunt !

Installer et configurer une tâche Grunt

Avant de configurer une tâche, vous devez installer son plugin. Prenons un exemple très commun : je possède plusieurs fichiers Javascript que je dois concaténer en un seul. Le plugin Grunt pour cette tâche est grunt-contrib-concat(veuillez noter que les plugin portant le nom de contrib-*sont des packages ‘officiels’, dont la liste complète est ici.

Pour installer un plugin, vous devez le faire via la ligne de commande, pour la concaténation via contrib-concat, la commande est la suivante :

npm install grunt-contrib-concat --save-dev

Remarquez que votre fichier package.json s’est automatiquement mis à jour (grâce au flag --save-dev) avec une nouvelle dépendance.

Nous devons maintenant configurer notre tâche. Retournons à notre fichier Gruntfile.js et commençons la configuration. Le code est commenté avec les explications :

module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

/*
1. Je configure ma tâche
(la doc de chaque package vous fournira les options disponibles)
*/
concat: {
options: {
separator: ';',
},
dist: {
src: ['js/jquery.js', 'js/plugins.js','js/main.js'],
dest: 'js/app.js'
}
}

});

// 2. Je charge ma tâche
grunt.loadNpmTasks('grunt-contrib-concat');

// J'assigne ma tâche à la commande par défaut de Grunt
grunt.registerTask('default', ['concat:dist']);
};

Vous êtes prêt à éxécuter votre première tâche ! Retournez en ligne de commande et lancez la commande :

grunt

gruntdemo 1 GruntJS pour les Nuls !

Comme vous pouvez le constater, Grunt a automatiquement créé le fichier app.js que vous lui avez demandé dans la configuration du plugin. Magique !

Ajoutons une tâche

Maintenant que vous avez compris comment configurer une tâche, il devient très facile d’ajouter de nouvelles tâches à notre projet. Prenons un autre exemple commun : compiler du CSS écrit en SASS. Nous aurons besoin pour cela de grunt-contrib-sass, que nous installerons de la même manière que précédemment :

npm install grunt-contrib-sass --save-dev

Nous ajoutons ensuite la configuration de notre tâche, puis son chargement, et enfin son éxécution :

module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

// Concaténation
concat: {
options: {
separator: ';',
},
dist: {
src: ['js/jquery.js', 'js/plugins.js','js/main.js'],
dest: 'js/app.js'
}
},

// Nouvelle tâche
sass: {
dist: {
options: {
style: 'expanded'
},
files: {
'css/style.css': 'css/*.scss',
}
}
}

});

// 2. Je charge ma nouvelle tâche
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-sass');

// Je l'ajoute à ma commande par défaut
grunt.registerTask('default', ['concat:dist', 'sass:dist']);
};

Executez à nouveau gruntet votre fichier style.css sera créé !

Distinguer les tâches de développement / de production

C’est toute la force de Grunt : vous remarquez que vous pouvez assigner plusieurs types de tâches via grunt.registerTask();. La commande grunt est la commande par défaut, mais vous pouvez pour un package définir plusieurs types de tâches ! Reprenons l’exemple précédent : nous allons ajouter 1 package, grunt-contrib-uglify, et ajouter un peu de code pour optimiser sass :

module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

// Concaténation
concat: {
options: {
separator: ';',
},
dist: {
src: ['js/jquery.js', 'js/plugins.js','js/main.js'],
dest: 'js/app.js'
}
},

// Compilation
sass: {
dist: {
options: {
style: 'expanded'
},
files: {
'css/style.css': 'css/*.scss',
}
},
prod: { // Nous ajoutons 'prod' qui compilera le code en mode compressé
options: {
style: 'compressed'
},
files: {
'css/style.min.css': 'css/*.scss' // Nous ajoutons .min au nom de notre fichier
}
}
},

// Minification JS
uglify: {
options: {
separator: ';',
},
dist: {
src: ['js/jquery.js', 'js/plugins.js','js/main.js'],
dest: 'js/app.min.js'
}
}

});

grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');

// je possède désormais 2 tâches
grunt.registerTask('default', ['concat:dist', 'sass:dist']);
grunt.registerTask('prod', ['uglify:dist', 'sass:prod']);
};

Nous avons donc une nouvelle commande : grunt prod. Vous développez votre application ? Lancez grunt. Une fois terminé, vous aurez sous la main la commande grunt prod pour faire automatiquement toutes les tâches qui vous prenaient bien des minutes auparavant !

Vous aurez donc remarqué 2 chose :

  • Nous pouvons lancer les plugins que nous souhaitons en fonction des commandes : Uglify n’est utilisé que pour la commande de production.
  • Pour un même plugin, nous pouvons le paramétrer différemment : Grunt Sass possède une configuration dist et prod que nous reportons à la fin lors de la définition des commandes.

Vous pouvez donc désormais charger les packages que vous souhaitez et définir des commandes qui lanceront les tâches souhaitées !

Il ne restait qu’un seul détail, je vous vois déjà venir…

« Ca a l’air vraiment super tout ça, mais je suis intégrateur CSS, et je vois pas où est le gain de temps si je dois lancer une ligne de commande à chaque fois que j’écris un peu de CSS… »

Heureusement pour nous, notre taureau favori a pensé à tout simple smile GruntJS pour les Nuls !

Le « live-changer » : grunt-contrib-watch

Maintenant que vous savez tout de GruntJS, parlons de grunt-contrib-watch, une tâche qui va « regarder » vos fichiers et actionner des tâches à la volée… et comme si cela ne suffisait pas, un livereload est inclus ! Un fichier modifié, et votre navigateur se met à jour tout seul…

Après avoir installé grunt-contrib-watch en ligne de commande, nous n’avons plus qu’à le configurer. Il suffit pour cela de lui dire où regarder et que faire lorsque ces fichiers sont modifiés. Reprenez votre fichier et configurons :

// ...

// Observons…
watch: {
options: {
livereload: true, // Activons le livereload du navigateur
},
src: {
files: ['js/*.js', 'css/**/*.scss', '**/*.html'], // Les fichiers à observer…
tasks: ['default'], // … la commande à effectuer
}
}

// ...

Notez que pour le livereload, vous devrez ajouter ce bout de code dans le head de votre html :

<script src="//localhost:35729/livereload.js"></script>

Vous n’avez plus qu’à lancer grunt watch, et passer les prochaines heures à travailler sans vous soucier du reste…

Il n’est pas nécessaire de versionner le dossier node_modules, vous aurez certainement deviné que nous vous incitons à créer votre fichier de configuration ainsi qu’un package.json contenant déjà les dépendances dont vous aurez besoin. Ainsi, à chaque nouveau projet, un simple npm install et votre workflow grunt est prêt à être utilisé.

GruntJs n’est pas seul

Nous vous avons fait découvrir en quoi GruntJS est un outil indispensable pour tous développeurs. Une fois adopté, il est (vraiment) difficile de s’en passer. Nous vous avons fait ici un exemple détaillé mais succint de GruntJS, les possiblités offertes par les packages sont denses : créer des Fonctions depuis un dossier SVG, compresser automatiquement les images d’un dossier, lancer un serveur local, et bien d’autres… à peu près tout est possible avec Grunt !

Cependant, d’autres TaskRunner existent et c’est le cas par exemple de GulpJS, qui offre les mêmes possibilités, avec une approche différentes.

Enfin, nous pourrions développer encore longuement notre article en vous fournissant de nombreux conseils sur l’optimisation de notre fichier de configuration. Vous avez des conseils pour optimiser l’utilisation de GruntJS ? Un bon package à nous conseiller ? Des astuces à nous donner ? Partagez vos infos en commentaires !

  1. Bonjour,

    Moi, je viens de me mettre à Grunt, mais je me demande si je n’aurais pas dû passer directement à Gulp en raison de son traitement des tâches simultanée. Par contre, ce dernier semble plus complexe à appréhender…

    Avez-vous déjà testé un plugin tel que « grunt-remcss », Qui supprime les CSS inutilisés ? Quid du js qui utilise certaines classes ?

Comments are closed.