Introducción a Grunt

Author Top
enzo

Hoy vengo a hablarles de unas de esas herramientas que hacen parte del set de Sexy y Hot de las que todos los developers hablan, si muy a nuestro pesar otra herramienta mas que al parecer hay que aprender :P.

De mi propia experiencia se lo difícil es que tener el tiempo suficiente para poder aprender todas estas herramientas Sexys, voy a explicarlo de la forma mas practica y sencilla posible.

1. Que es Grunt.

Grunt es una herramienta para automatizar tareas es nuestros proyectos, hasta donde se proyectos web. La idea es que todas esas tareas rutinarias que debemos hacer en nuestros proyectos Grunt las haga por nosotros. Entre las tareas mas comunes están:

  • Concatenación de archivos (CSS, JS, etc)
  • Minificación de archivos (CSS, JS, etc)
  • Optimización de imágenes.
  • Compilación ( SASS -> CSS y otros)
  • Unit Test

Cada una de estas tareas se implementa por un plugin de Grunt, que al día de hoy cuenta con casi tres mil plugins, puedes ver la lista completa de plugins en http://gruntjs.com/plugins

Una de la ventajas adicionales que tiene Grunt es que es Javascript al igual que los plugins y utiliza NodeJS  para su ejecución lo que lo hace multi plataforma.

2. Como instalo Grunt.

Como dije anteriormente Grunt utiliza NodeJS para su ejecución, pero no necesitamos saber nada de NodeJS para poder utilizar Grunt, nada mas necesitamos instalarlo de la misma forma que no necesitamos conocer de Java para ejecutar programas que utilicen del JRE de Java.

Lo primero es instalar NodeJS y puedes encontrar un instalador de NodeJS para tu plataforma en http://nodejs.org/download/.

Luego de instalar NodeJS ya tendremos el NPM (Node Packaged Modules) el cual nos permite instalar paquetes listados en https://www.npmjs.org, al dia de hoy registra casi 80 mil paquetes y uno de ellos es Grunt. 

Primero instalamos el paquete grunt-cli que es una interfaz de linea de comando para interactuar con grunt con el siguiente comando.

npm install grunt-cli -g

La opción -g indica que se instala global al sistema y no local.

Ahora para instalar el paquete grunt que es el que ejecuta las tareas tenemos dos opciones.

2.1 Definir package.json

Dentro de nuestra aplicación debemos crear un archivo llamado package.json que sera leído por el comando npm:

{
  "name": "example-project",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.1"
  }
}

Posteriormente ejecutamos el comando:

$ npm install

El cual leerá el archivo package.json y procederá a la instalación de grunt y sus dependencias generando una salida similar a la siguiente.

grunt@0.4.5 node_modules/grunt
├── which@1.0.5
├── dateformat@1.0.2-1.2.3
├── eventemitter2@0.4.13
├── getobject@0.1.0
├── rimraf@2.2.8
├── colors@0.6.2
├── hooker@0.2.3
├── async@0.1.22
├── grunt-legacy-util@0.2.0
├── exit@0.1.2
├── lodash@0.9.2
├── coffee-script@1.3.3
├── underscore.string@2.2.1
├── iconv-lite@0.2.11
├── nopt@1.0.10 (abbrev@1.0.5)
├── minimatch@0.2.14 (sigmund@1.0.0, lru-cache@2.5.0)
├── grunt-legacy-log@0.1.1 (underscore.string@2.3.3, lodash@2.4.1)
├── findup-sync@0.1.3 (lodash@2.4.1, glob@3.2.11)
├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
└── js-yaml@2.0.5 (esprima@1.0.4, argparse@0.1.15)

Grunt y sus dependencias quedaran dentro del folder node_modules y nuestro árbol de directorios sera similar al siguiente.

$ tree -L 3
.
├── node_modules
│   └── grunt
│       ├── CONTRIBUTING.md
│       ├── LICENSE-MIT
│       ├── README.md
│       ├── appveyor.yml
│       ├── internal-tasks
│       ├── lib
│       ├── node_modules
│       └── package.json
└── package.json

2.2 Generar dependencias en package.json

Si no sabemos que version necesitamos podemos hacer que grunt autogenere las dependencias en el archivo package..json, primero creamos un archivo genérico como el que se muestra a continuación:

{
  "name": "example-project",
  "version": "0.1.0",
  "devDependencies": {
  }
}

Ahora ejecutamos la instalación de grunt informando que deseamos que deseamos que autogenere las dependencias como se muestra en el siguiente comando:

$ npm install grunt --save-dev

Luego de instalar grunt y sus dependencias nuestro archivo package.json lucirá similar al siguiente listado:

{
  "name": "example-project",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "^0.4.5"
  }
}

3. Crear tareas para Grunt.

Llegado a este punto ya tenemos todo lo necesario para inicia la construcción de las tareas que deseamos utilizar, lo primero que debemos hacer es crear un archivo Gruntfile.js para definir las tareas que deseamos automatizar.

Veamos un archivo mínimo de Grunt.

'use strict';

module.exports = function (grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
    });

    // Where we tell Grunt we plan to use some plug-ins.
    //grunt.loadNpmTasks('grunt-contrib-xxxx');


    // Where we tell Grunt what to do when we type "grunt" into the terminal.
    //grunt.registerTask('default', ['xxxx']);
};

Como se ve tenemos 3 secciones.

  • InitConfig: En esta area definimos las tareas que ejecutara Grunt
  • LoadNpmTask: Se debe hacer una carga del plugin adecuado para las tareas que deseamos definir.
  • RegisterTask: Debemos registrar las tareas que se van a ejecutar, estas pueden ser mucho mejor a las tareas definidas.

3.1 Instalar plugin.

A manera de ejemplo vamos a instalar el plugin concat para unir archivos, para esto ejecutamos el siguiente comando dentro del folder de nuestro proyecto.

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

La opción --save-dev modifica el archivo package.json para agregar la dependencia.

3.2 Uso del plugin. 

Con el plugin concat instalado ahora solo debemos configurar en el archivo Gruntfile.js como se muestra a continuación.

'use strict';

module.exports = function (grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        concat: {
            dist: {
                src: [
                    'js/libs/*.js', // All JS in the libs folder
                    '/js/global.js'  // This specific file
                ],
                dest: '/js/build/production.js',
            }
        }
    });

    // Where we tell Grunt we plan to use some plug-ins.
    grunt.loadNpmTasks('grunt-contrib-concat');

    // Where we tell Grunt what to do when we type "grunt" into the terminal.
    grunt.registerTask('default', ['concat']);
};

Con esta definición indicamos donde están los archivos que deseamos concatenar y donde debe quedar el destino, luego cargamos el paquete NPM y por ultimo registramos la tarea.

Como se puede ver en el origin de los archivos a concatenar se hace uso del carácter especial * para definir un grupo amplio de archivos.

3.3 Ejecutar tarea.

Para ejecutar la tarea solo debemos utilizar alguno de los siguientes comandos:

$ grunt

$ grunt concat

El primer comando ejecuta todas las tareas disponibles y el segundo la tarea especifica concat, como solo tenemos el resultado sera el mismo y obtendremos una salida similar a la siguiente.

Running "concat:dist" (concat) task
File "web/js/build/production.js" created.

Done, without errors.

Podemos seguir aumentando nuestras tareas como por ejemplo a la salida del concat  agregar una tarea para minify el archivo, todo depende de lo que necesitemos el limite son los cerca de 3.000 plugins para grunt y las necesidades de nuestro proyecto.

Espero que haya sido de su agrado.