December 13, 2013

Grunt

Grunt es lo que necesitas

by ZeroDragon
Categories: stuff, tecnologia
Tags: , , , , ,
Comments: 1 Comment

Hace unas semanas empecé a trabajar con grunt en mis desarrollos. Básicamente fue una evolución de trabajo. Un poco más atrás empecé a implementar LESS para simplificar mi CSS. Unos días después implementé coffeescript para darle más poder al javascript. Finalmente me dio curiosidad de alguna forma para simplificar el HTML. Así que implementé Jade… He de mencionar que mi código se ve muy limpio, bastante zen diría yo. Sin embargo, me di cuenta de un problema. Por cada nuevo lenguaje, requería compilar todos los archivos para poder probar los cambios.

Poco a poco fui metiendo más y más plugins a mi Sublime Text 3, si, uso el 3, like a boss; con el propósito de compilar al vuelo en cada guardado. Siendo yo un purista, me incomodó tener tantos plugins encima alentando mis procesos (Si bien no se alentaba nada, en mi mente me hacían ruido).

Mientras estaba leyendo algo sobre MEAN Stack. Vi que usan Grunt para automatizar procesos, eso me llamó la atención y me puse a investigar. A continuación les escribo un pequeño tutorial de como instalar y configurar grunt.

Requerimientos

Primero que nada hay que saber que grunt corre en node.js. Así que si no tienes node. Te sugiero instalarlo en tu máquina. Yo lo instalé usando homebrew.

Primer paso [Instalando grunt]

Ok el primer paso es instalar el CLI de grunt. Esto lo haces desde la terminal así:

$> npm install -g grunt-cli

Esto habilitará el comando grunt en tu consola. Ahora algo que a mi me hizo algo de ruido es que grunt como tal no es el CLI, si no que requieres instalarlo dentro de tu repositorio, a continuación veremos como se hace.

Segundo paso [Usando el Node Package Manager]

Grunt necesita estar dentro de tu repositorio para funcionar, así que hay que instalarlo. Aquí pongo un zip con todo… no, no es cierto. Para instalarlo necesitas crear un archivo llamado package.json en la raíz de tu repositorio. Nota, si estás usando git. te aconsejo agregar node_modules/ a tu .gitignore. Solo hazlo ;)
En tu package.json vamos a poner lo siguiente

{
  "name": "El-Nombre-de-Mi-Proyecto",
  "version": "x.x.x", #Algo asi como 0.1.0
  "devDependencies": {
    #Le decimos al NPM que queremos la versión 0.4.2 o mayor de grunt
    "grunt": "~0.4.2",
  }
}

Una vez listo, vamos a la consola, navegamos al directorio de nuestro proyecto y corremos:

$> npm install

Esto creará un directorio en la raíz de tu proyecto llamado node_modules (si no es que ya existe) y podrá ahí todos los archivos de grunt (ves, por eso te dije que lo pusieras en el .gitignore).

Ok ya tienes grunt instalado y funcional. Pero aun te falta configurarle que va a hacer cuando lo ejecutes; ese es el siguiente paso.

Tercer paso [Configurando grunt]

Grunt necesita saber que va a hacer en tu proyecto. Eso lo defines en un archivo llamado Gruntfile.js o Grunfile.coffee. Si ya usas coffee (y deberías) te recomiendo uses la versión con cafeína, simplemente porque es más estético y no necesitas compilarlo a js.

Para iniciar tu objeto de grunt es:

module.exports = (grunt) ->

Ok, nada difícil. Ahora vamos a definir dentro del objeto de grunt algunas tareas. Es importante entender que grunt por si mismo es solo el trabajador, pero necesita un set de instrucciones para hacer lo que le pides. Entonces digamos que quieres hacer una tarea sencilla para observar cada que hagas un cambio en un archivo. Esto lo haces con el set de tareas grunt-contrib-watch. ¿Como instalas este set de tareas? Pues lo defines dentro de tu package.json. No te preocupes, vamos a realizar un ejercicio de principio a fin paso a paso.

Cuarto paso [Ejecutando mi primera tarea]

Okay, para esta primera tarea vamos a hacer que grunt observe los archivos .less en el directorio public/css/src/ de mi framework y que cada vez que se haga un cambio, los compile en un respectivo .css y cree a partir de ese un .min.css, luego borre el archivo temporal .css y finalmente haga un refresh en mi navegador para ver los cambios.

Esto lo logramos con el set de tareas grunt-contrib-watch, grunt-yui-compressor, grunt-contrib-clean y grunt-contrib-less. Vamos a ir a nuestro package.json y ahí lo vamos a instanciar de la siguiente forma:

{
  "name": "El-Nombre-de-Mi-Proyecto",
  "version": "x.x.x", #Algo asi como 0.1.0
  "devDependencies": {
    #Le decimos al NPM que queremos la versión 0.4.2 o mayor de grunt
    "grunt": "~0.4.2",
    #Solicitamos los sets de tareas y realmente no nos interesa la versión.
    "grunt-contrib-watch": "",
    "grunt-yui-compressor": "",
    "grunt-contrib-less": "",
    "grunt-contrib-clean": ""
  }
}

Ahora vamos a nuestra consola y escribimos

$> npm install

Para instalar lo que haga falta. Si ya habías instalado grunt como lo hicimos en el primer paso, no te preocupes que solo va a instalar lo que haga falta, no va a reinstalar nada que ya exista.

Listo, ya debes tener instalado los sets de tareas que necesitamos. El siguiente paso es configurar tu Gruntfile.coffee:

module.exports = (grunt) ->
  grunt.loadNpmTasks 'grunt-contrib-watch' //Cargamos las tareas de watch
  grunt.loadNpmTasks 'grunt-yui-compressor' //Cargamos las tareas de watch
  grunt.loadNpmTasks 'grunt-contrib-less' //Cargamos las tareas de watch
  grunt.loadNpmTasks 'grunt-contrib-clean' //Cargamos la escoba :P

Ahora necesitamos definir la tarea defaul (la tarea que se va a ejecutar cuando ejecutes grunt desde CLI)

grunt.registerTask('default', ['watch']);

Con esto creamos una tarea con el nombre default que estará apuntando a una especificación watch. Ahora tenemos que crear dicha especificación:

grunt.initConfig { //primero definimos la configuración inicial
    watch:{ //Creamos la especificación watch
        // Y le hacemos un scope para los CSS, de esta forma podemos tener
        // diferentes acciones para diferentes archivos
        css:{ 
            //Especificamos que observe todos los .less del folder
            files: ['public/css/src/*.less'],
            //Definimos que tareas va a hacer cuando hayan cambios
            tasks: [ 'less', 'cssmin', 'clean' ],
        }
        options{
            //Con esto convertimos la tarea en recurrente
            forever:true,
            //Esta simple línea de código nos dispara el refresh en el navegador
            livereload:true,
    },

GREAT!. Lo que hicimos hasta ahora fue crear la configuración inicial y especificarle a grunt que tareas va a hacer cuando hayan cambios en los .less. Si te diste cuenta, mandé a llamar tres tareas less, cssmin y clean. Estas tareas aun no están creadas. Vamos a hacerlas.

    less:{ //obvio el nombre de mi tarea
        compile:{ //de nuevo el scope
            files:{
                //pedimos que compile style.less en style.css
                'public/css/src/style.css':['public/css/src/style.less']
            }
        }
    },
    cssmin:{
        dist:{
            files:[
                {
                 //Mandamos a crear el min.css a partir del .css
                 'src':'public/css/src/style.css',
                 'dest':'public/css/style.min.css'
                }
            ]
        }
    },
    clean:{
        css:{
            //Borramos el .css temporal
            src['public/css/src/*.css']
        }
    }

Ahora solo nos falta integrar el livereload en nuestro navegador. Ojo hay dos formas:

  1. 1 Con una extensión de chrome LiveReload [link]
  2. 2 Insertando este javascript en tu desarrollo:
    <script src="http://localhost:35729/livereload.js"></script>

TADA!. Si hiciste todo paso a paso, te deben quedar los dos archivos así como en este Gist

Ahora solo nos falta ir a la consola y escribir

grunt

Te saldrá algo como esto:

$> grunt
Running "watch" task
Waiting...

Vas a necesitar dar un refresh a tu navegador para que cargue la conexión al node.js del LiveReload.
Ahora ve a tu archivo .less que está dentro de public/css/src/ y haz un cambio.
Verás que grunt empieza a ejecutar todas las tareas que le dijiste, va a crear el css luego el min.css, borrar el css y finalmente hará un refresh en tu navegador.

¿Bastante interesante, no? Esto es solo una probada, pero con grunt puedes compilar tus jade, coffee, comprimir imágenes, etc, etc, etc.

¿Te interesa que ponga más cosas como estas?, no dudes en pedirlo. Si te gustó esto compártelo en todas tus redes sociales. Y si en realidad te sirve de algo lo que escribo aquí, a la derecha hasta arriba hay un botón para que me invites un café o algo más :D

Zero out