Accueil > Web > Configurer Grunt pour votre premier build en javascript

Configurer Grunt pour votre premier build en javascript

Introduction

Dans le précédent article, je présentais Grunt d’un point de vue fonctionnel, sans rentrer dans les détails techniques. Ce second article va donc s’intéresser plus directement à l’installation et à la configuration de Grunt pour parvenir à réaliser ses tâches et workflows personnalisés afin de faciliter au mieux le développement du projet. Plus tard, un troisième article vous apprendra comment définir vos propres tâches complexes.

Pour des raisons pratiques, nous allons utiliser comme fil rouge la mise en place des workflows d’une application web présente sous la forme d’une unique page index.html avec du javascript et du CSS.

 

Mise en place

Prérequis

Pour ceux qui n’ont jamais eu l’occasion de travailler avec Node.js / npm, nous allons voir comment les installer. Le mieux serait de l’installer en téléchargeant la dernière version sur le site officiel. Cependant, vous pouvez également l’installer rapidement via votre gestionnaire de paquets si vous être sous un OS Debian-like (pour les autres, voir ce tutoriel), même s’il ne s’agira pas forcément de la version la plus à jour :

Le package npm sera installé automatiquement avec. Il s’agit du gestionnaire de paquets de Node.js. Il va nous permettre d’installer très simplement des tâches Grunt qui sont pour la quasi-totalité référencées sur npm. Il faut savoir qu’il existe deux façons d’installer un package :

  • en global avec npm install -g nomDuPackage, ce qui le rend accessible partout sur votre ordinateur
  • en local avec npm install nomDuPackage, ce qui va l’installer dans un sous-dossier node_modules.

Pour exécuter un fichier javascript avec Node.js, il suffit d’utiliser la commande node monFichier.js.

Le projet

Nous allons maintenant créer une application web simpliste pour nos exemples. Les fichiers dont nous avons besoin se trouvent tous dans ce dépôt Git. Clonez le dépôt (ou téléchargez le zip pour l’extraire à l’endroit de votre choix). Une fois le projet récupéré, vous pouvez ouvrir la page index.html dans votre navigateur pour voir la page qui servira pour nos tests.

Installer Grunt

Maintenant que nous avons notre application basique, nous allons pouvoir nous concentrer sur Grunt en lui-même. Il y a deux éléments à installer. Tout d’abord, installons le package global :

Puis nous allons installer le package local, en n’oubliant pas de créer au passage un fichier package.json pour stocker nos dépendances. Ce fichier permet à npm de « mémoriser » les dépendances de notre projet en indiquant les paquets à installer et leur version. De cette manière, il suffit pour un développeur d’exécuter la commande npm install dans le même répertoire que le fichier pour que soient installés tous les modules nécessaires au projet.

Les dépendances peuvent être de deux types : les devDependencies qui ne servent que pendant l’étape de développement (par exemple les librairies de tests), et les dependencies qui servent toujours. Ici, il s’agit d’une dépendance utile simplement quand nous développons, donc pour demander à npm de sauvegarder notre dépendance dans le package.json, nous utilisons l’option --save-dev (sinon nous aurions utilisé --save).

Vous pouvez ouvrir votre fichier package.json et constater que grunt a bien été rajouté par npm dans les dépendances.

Le Gruntfile

Maintenant que tout est installé, il est temps de commencer à configurer Grunt ! Tout se passe dans un seul fichier, le fichier Gruntfile.js. Celui-ci va définir toutes les tâches qui pourront être exécutées. Et le contenu minimal de ce fichier tient sur… une ligne !

Bbien évidemment, un fichier aussi minimal ne permet de lancer aucune tâche, mais c’est dans cette simple fonction que nous allons oeuvrer. On peut remarquer l’objet grunt passé en argument qui expose de nombreuses fonctionnalités que nous allons pouvoir utiliser pour configurer Grunt.

La première méthode que nous allons voir, grunt.initConfig(), est la plus importante, puisqu’elle va nous permettre de configurer chacun des plugins que nous allons utiliser par la suite. Elle prend en argument un simple objet qui contiendra les paramètres à passer aux plugins (Grunt privilégie la configuration au code) :

Charger les plugins Grunt

Un plugin Grunt doit être chargé avec grunt.loadNpmTasks('nom-du-plugin');. Pour nous simplifier la vie, il existe un plugin qui va charger automatiquement tous les modules présents dans notre package.json dont le nom commence par grunt-, ce qui représente la quasi-totalité des plugins Grunt. Commençons par l’installer :

Puis nous appelons simplement le plugin dans notre code :

Maintenant que tout est installé, nous allons pouvoir réfléchir à ce que nous voulons faire.

Lorsqu’on souhaite envoyer notre site en production, nous allons assembler et minifier nos fichiers CSS (même s’il n’y en a qu’un pour l’instant). Puis nous allons minifier et regrouper en un seul fichier nos ressources javascript et donc remplacer automatiquement les scripts inclus dans notre page index.html. Tout cela permettra de générer un dossier dist contenant les sources de notre application.

Configuration de notre GruntFile

Créer nos tâches principales

Nous allons donc avoir une tâche principale qui, par convention, s’appelera build et qui sera chargée de générer ce dossier dist prêt pour une mise en production.

Avec Grunt, cela se fait très facilement grâce à la méthode grunt.registerTask qui prend comme paramètres le nom de la tâche à créer, et la liste des tâches à appeler.

Attention ! Il convient, avant de lire la suite, d’étudier la façon dont sont représentés les fichiers. En effet, pour faciliter le développement et l’utilisation des plugins, Grunt met en place une abstraction très performante pour cibler ceux-ci. Les explications justifieraient à elles seules l’écriture d’un article, je vous recommande donc de consulter la documentation à ce sujet pour appréhender tous les différents formats utilisables et leurs possibilités.

Copier les fichiers

Pour générer un dossier dist contenant notre site prêt à être mis en production, il va nous falloir copier tous les fichiers dont nous avons besoin. Cela peut être réalisé très simplement grâce à la tâche copy. Installons-la directement :

Il nous suffit simplement d’indiquer les fichiers à copier et la destination. Nous ne prenons pas en compte ici les fichiers javascript et CSS qui seront copiés d’une autre façon. Voici le rendu de la configuration :

A chaque appel à la tâche build, nos fichiers vont être copiés dans le répertoire dist/. Mais cela signifie également qu’à chaque appel, les fichiers précédemment copiés seront toujours là ! En général, cela ne pose pas de soucis, mais si nous supprimons un fichier dans notre projet, il y a fort à parier qu’il sera toujours présent dans le répertoire dist/ par la suite !

Il faut donc également penser à vider le répertoire avant de copier les fichiers, ce qui se fait aisément avec la tâche clean, que nous allons installer et configurer très facilement :

Regrouper et minifier les fichiers CSS

La tâche cssmin permet de regrouper les fichiers très simplement. Cela doit devenir un automatisme, nous allons installer le module npm correspondant :

Encore une fois, avec la documentation, la syntaxe est facile à prendre en main :

Regrouper et minifier les fichiers Javascript

L’équivalent de la tâche cssmin pour le javascript est uglify. Aucune surprise, le fonctionnement est très semblable :

Nous avons dorénavant nos fichiers javascript et css minifiés… Mais il reste un problème ! En effet, nos fichiers sont bien créés, mais ce sont toujours les anciens fichiers non minifiés qui sont inclus dans nos pages ! Nous allons voir maintenant comment rectifier cela.

Modifier les fichiers inclus

Voici le problème qui se pose : nous devons analyser le code source de nos pages pour retirer les inclusions de script et de css et les remplacer par des inclusions de nos fichiers uniques minifiés.

Une fois encore, un simple plugin va nous simplifier la vie ! Il s’agit cette fois-ci du plugin usemin. Je vous invite à consulter la documentation pour ce plugin, mais voici en résumé ce qu’il fait :

  • Une tâche useminPrepare va analyser le code des fichiers spécifiés à la recherche de blocs
  • Cette tâche configure ensuite les tâches précisées pour mettre en place un workflow de changements. Par défaut :
    • concat (qui permet de concaténer plusieurs fichiers en un seul) puis uglify pour le JS
    • concat puis cssmin pour le CSS
  • La tâche usemin remplace ensuite les blocs par la référence vers le bon fichier

Cela signifie entre autre que nous n’aurons plus besoin des configurations des tâches uglify et cssmin que nous avons mises en place plus haut. Enlevez-les donc ! Dorénavant, c’est usemin qui va s’en occuper. Pour la tâche concat, celle-ci est inutile car les fichiers seront déjà regroupés par les autres tâches dans notre cas. Passons tout de suite à la mise en place :

Dans le index.html, formez vos blocs de la façon suivante :

On configure ensuite nos workflows et les fichiers à analyser à la recherche des blocs :

Puis on indique où remplacer les blocs à usemin :

Enfin, on configure notre tâche build :

Il suffit alors de lancer notre tâche Grunt en se plaçant dans le répertoire principal lorsque l’on souhaite effectuer un build de notre application (par exemple en vue d’une mise en production) :

 

Conclusion

L’ensemble des sources de cet article est disponible sur ce dépôt Git.

Nous avons vu ici comment mettre en place une tâche de mise en production pour notre application, mais il faut garder à l’esprit que les possibilités de Grunt sont presque infinies !

Comme nous l’avons constaté, il existe de très nombreux plugins permettant d’effectuer presque toutes les tâches possibles et imaginables. Il existe cependant des cas où ceux-ci ne suffiront pas.

Dans cette optique, nous verrons dans un troisième article la manière de créer nos propres tâches Grunt personnalisées.

Categories: Web Tags: , , , ,
  1. Pas encore de commentaire
  1. Pas encore de trackbacks


6 + sept =