Grunt: Qué es y Cómo se Utiliza

JavascriptNode.js

Si estás dentro del mundillo del desarrollo frontend seguramente hayas escuchado hablar de Grunt, una aplicación que te permitirá automatizar tareas y que funciona sobre Node.js. Si ya has usado esta herramienta quizás te haya resultado algo confusa, tal y como me ocurrió a mi en su día la primera vez que intenté instalarla y configurarla. Además también es muy habitual que, aunque la hayas instalado, no tengas claro cómo sacarle provecho, pensando que quizás es una pérdida de tiempo.

En este tutorial vamos a ver qué es Grunt y cómo puedes utilizarlo. Esta es una guía introductoria, por lo que veremos cómo instalarlo y configurarlo partiendo absolutamente desde cero. Además también verás algunos consejos para optimizarlo, de modo que en lugar de darte quebraderos de cabeza pueda resultarte útil. Además, integraremos Sass en el proyecto, configurando Grunt para que compile automáticamente el código Sass de nuestro proyecto, además del código JavaScript.

En este tutorial aprenderás los siguientes conceptos:

  • Conceptos básicos de Node.js, de modo que puedas utilizar Grunt.
  • Cómo integrar Sass en tu proyecto y cómo compilar sus archivos con Grunt.
  • Cómo minificar código JavaScript, obteniendo un único archivo como resultado.
  • Cómo configurar el comando watch para compilar todo automáticamente cuando se detecten cambios.

Existen ciertos conocimientos que deberías tener antes de seguir este tutorial. Por ejemplo deberías saber crear una página web con HTML, CSS y JavaScript. Además también deberías tener ciertos conocimientos acerca de la línea de comandos; si no los tienes, consulta el tutorial de introducción a la línea de comandos. De todos modos, bastará con que conozcas el comando pwd para mostrar el directorio actual, el comando ls para listar archivos y directorios y el comando cd para cambiar de directorio.

Qué es Grunt

Grunt es una aplicación para gestionar tareas que te permitirá automatizarlas. No es la única aplicación con este propósito, puesto que también tenemos a Gulp, que es otra de las más utilizadas. La idea es que una vez automatices ciertas tareas ya no tengas que preocuparte de ellas. Obviamente, como todo, requiere una configuración inicial

Algunas de las tareas que podrás realizar son cosas como la minificación automática de los archivos JavaScript de tus proyectos, de modo que todo el código se compile en un único archivo del menor tamaño posible. Otra tarea muy habitual es la compilación y minificación automática del código de preprocesadores CSS como pueden ser Sass o LESS.

Información! Si ya sabes lo que son tanto Node.js como npm, puedes saltarte sus definiciones y pasar a la siguiente sección.

Acerca de Node.js

Tanto Gulp como Grunt funcionan bajo Node.js, que es un entorno de ejecución JavaScript que se utiliza en el lado del servidor. JavaScript fue un lenguaje de programación frontend que se ejecutaba en los navegadores hasta la aparición de Node.js, cuando comenzó a ser también un lenguaje backend que puede ejecutarse tanto en un servidor como en un sistema local, permitiendo la creación de herramientas de desarrollo como Grunt.

Acerca de npm

El gestor de paquetes npm se utiliza para instalar y configurar paquetes de Node.js. Utiliza el mayor repositorio de paquetes de JavaSript, pudiendo instalar paquetes tanto localmente (por proyecto) como globalmente (compartidos por todo el sistema).

Cuando instalas paquetes localmente a un proyecto usarás el comando npm y cuando los instalas globalmente usarás el comando npm -g, instalándose en todo el sistema.

Con npm también se gestionarán automáticamente las depenendecias de los paquetes, de modo no tengas que estar pendiente de ellas. Es decir, cuando instales un paquete, se instalarán también aquellos paquetes adicionales requeridos por dicho paquete.

Cómo Instalar Grunt

En esta sección utilizaremos ciertos comandos para instalar Grunt, por lo que dependiendo de tu sistema operativo haremos uso de la terminal de macOS, de la terminal de Linux o de la terminal de Windows. Si usas Windows, también podrías utilizar la terminal de Linux para Windows o Git Bash, que es un emulador de terminal de Linux que se incluye con la instalación de Git.

Instalación de Node.js y npm

Grunt requiere que tengas Node.js instalado en tu sistema. Así que si no tienes Node.js en tu sistema tienes dos opciones; por un lado puedes consultar el tutorial de introducción a npm y Node.js, y por otro puedes consultar las siguientes guías de instalación rápidas. Dependiendo de tus sistema operativo, sigue las instrucciones que se muestran a continuación:

  • Windows: Para instalar tanto Node.js como npm en Windows, debes descargar e instalar el instalador oficial. Si tienes problemas, consulta el tutorial de instalación de Node.js en Windows.
  • Linux: Para instalar tanto Node.js como npm en Linux, pudes consultar la guía de instalación Node.js en Ubuntu, la guía de instalación de Node.js en CentOS o, para una instalación genérica, instalar nvm mediante el comando:
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash

    Luego instala Node.js mediante el este comando:

    nvm install node

    Y finalmente usa el comando nvm use node para poder utilizar Node.

  • Mac: Para instalar tanto Node.js como npm en macOS tienes varias opciones.
    • Por un lado puedes instalar Node mediante nvm con el siguiente comando, que instalará nvm:
      curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash

      Luego instala Node.js mediante el comando nvm install node y finalmente comienza a usar node utilizando el comando nvm use node.

    • También puedes instalar Node.js mediante Homebrew, que es otro gestor de paquetes. Para ello, primero debes instalar XCode y Homebrew siguiendo este tutorial, o alternativamente, mediante los siguiente comandos:
      xcode-select --install

      Ahora instala Homebrew mediante este comando:

      /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

      Y finalmente instala Node.js y nom mediante el comando brew install node.

    Y tras esto ya deberías tener Node.js instalado en tus sistema.

A continuación puedes encontrar cómo instalar Grunt en diferente sistemas operativos. Lo que haremos será instalar Grunt globalmente, de modo que podamos utilizar esta herramienta con cualquier proyecto del sistema.

Instalación de Grunt

Si ya tienes tanto Node.js como npm instalados en tu sistema, podrás instalar Grunt mediante el siguiente comando, que podrás introducir en una ventana de terminal de macOS, de terminal de Linux o de símbolo del sistema o Git bash en Windows:

npm install -g grunt-cli

Ahora la línea de comandos de tu sistema operativo ya debería reconocer los comandos de Grunt. Si lo que has visto te ha parecido complicado, lo bueno es que no tendrás que repetirlo jamás. Podrás instalar casi cualquier aplicación basada en Node.js mediante un sencillo comando. Lo único de lo que te tendrás que preocupar es quizás de actualizar Grunt de vez en cuando.

Configuración del Proyecto

En este proyecto vamos a configurar Sass, que luego configuraremos con Grunt a modo de ejemplo, por lo que tendremos que instalarlo y configurarlo.

Instalación de Sass

Si tienes tiempo, consulta el tutorial de introducción a Sass, aunque también puedes instalarlo siguiendo los pasos que ves a continuación:

  • Windows: En caso de que no tengas Ruby instalado en tu sistema, primero descarga Ruby desde aquí y luego instala Sass mediante el comando gem install sass, que tendrás que ejecutar en modo administrador.
  • Linux: Vamos a ver las instrucciones para Ubuntu. Primero instala Ruby mediante el siguiente comando:
    sudo apt install ruby-full rubygems

    Y finalmente instala Sass mediante el comando sudo gem install sass.

  • Mac: En caso de que uses macOS, Ruby viene ya instalado de serie, pero si la versión de Ruby es inferior a la versión 2.0.0, ejecuta primero el comando sudo gem install ruby. Seguidamente instala Sass mediante el comando sudo gem install sass.

Inicialización del proyecto

Llegados a este punto vamos a comenzar con la creación de un proyecto en sí. Como quizás ya sepas, cualquier proyecto de Node.js necesita ser inicializado, creándose en dicha inicialización un archivo llamado package.json, que tal y como su extensión nos indica está en formato JSON.

Lo primero que debes hacer es crear un directorio para tu proyecto. En mi caso le llamará tutorial-grunt, y lo craré en mi directorio de proyectos de Node, al que suelo llamar code:

mkdir code/tutorial-grunt

Accedo al directorio:

cd code/tutorial-grunt

Ahora usa el siguiente comando para inicializar el proyecto:

npm init

Se te harán una serie de preguntas. Introduce los valores por defecto (versión licencia… etc), una descripción del proyecto y tu nombre. Si abres el archivo package.json, verás que contiene los datos que has introducido:

{
  "name": "tutorial-grunt",
  "version": "1.0.0",
  "description": "Tutorial de Grunt Neoguias.com",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Edu Lazaro",
  "license": "ISC"
}

Ahora vamos a configurar Grunt con el proyecto instalando el paquete de Grunt:

npm install grunt -D

El flag -D se utiliza para indicar que queremos instalar el paquete solamente en nuestra versión de desarrollo. Es útil cuando quieres instalar herramientas que solamente usarás en tu entorno local.

Además, vamos a instalar también otros paquetes necesario que podrás instalar del mismo modo que hemos visto, mediante el comando npm install nombre-paquete -D:

  • grunt-contrib-sass: Sirve para compilar código Sass a CSS. Puedes instalarlo con el comando npm install grunt-contrib-sass -D. Más información aquí.
  • grunt-postcss: Se aplicarán ciertas directivas post-procesado al CSS resultante mediante la librería PostCSS. Puedes instalarlo con el comando npm install grunt-postcss -D. Más información aquí.
  • autoprefixer: Simplemente un plugin de PostCSS. Puedes instalarlo con el comando npm install autoprefixer -D. Más información aquí.
  • grunt-contrib-cssmin: Tal y como su nombre indica, se usa para minificar código JavaScript. Puedes instalarlo con el comando npm install grunt-contrib-cssmin -D. Más información aquí.
  • grunt-contrib-uglify: Se usa para minificar código JavaScript. Puedes instalarlo con el comando npm install grunt-contrib-uglify -D. Más información aquí.
  • grunt-contrib-watch: Esta utilidad permite ejecutar ciertas tareas según unas reglas que podremos configurar. Podremos compilar automáticamente nuestro código CSS y JS cuando modifiquemos cualquier archivo. Puedes instalarlo con el comando npm install grunt-contrib-watch -D. Más información aquí.

Cuando acabes de instalar estos paquetes, abre el archivo package.json. Verás que ahora contiene los siguientes paquetes en la sección devDependences, indicando que estos paquetes se usarán solamente de forma local, durante el desarrollo de la aplicación:

"devDependencies": {
    "autoprefixer": "^9.8.0",
    "grunt": "^1.1.0",
    "grunt-contrib-cssmin": "^3.0.0",
    "grunt-contrib-uglify": "^4.0.1",
    "grunt-contrib-watch": "^1.1.0",
    "grunt-postcss": "^0.9.0"
  }
}

Si quieres, puedes agregar más paquetes a este archivo y luego instalarlos todos directamente ejecutando el comando npm install.

Creando el Archivo Gruntfile.js

Todo aquello que Grunt haga se lo tendrás que indicar tú, y puedes hacerlo mediante el archivo Gruntfile.js. En dicho archivo tendremos que cargar Grunt, definir las tareas a realizar, cargar los plugins necesarios y finalmente registrar las tareas.

Lo primero que tendrás que hacer es cargar Grunt, que es algo que puedes hacer mediante el siguiente código, que lee el archivo package.json:

module.exports = function (grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // Aquí creamos las tareas
  });
};

Cargando los Plugins de Grunt

Ahora vamos a cargar los plugins necesarios, que como podrás deducir, son los paquetes adicionales de Node que hemos instalado además de Grunt. Para registrar los plugins utilizaremos la función grunt.loadNpmTasks. Vamos a agregar el código necesario a lo que ya tenemos:

module.exports = function (grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // Aquí creamos las tareas
  });

  // Cargamos los plugins de grunt
  grunt.loadNpmTasks('grunt-contrib-watch');  
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-postcss');
  grunt.loadNpmTasks('grunt-contrib-uglify');
};

Como ves, hemos cargado todo menos el plugin de postCSS autoprefixer, que ya veremos luego cómo agregarlo.

Registro de Tareas en Grunt

Ahora vamos a registrar las tareas de Grunt, aunque tal y como puedes ver todavía no las hemos agregado, cosa que haremos luego. Por ahora registraremos todas tareas futuras; lo que sí adelantaremos es que una de ellas será la tarea 'default' por defecto, que se ejecutará cuando introduzcas el comando grunt en el directorio de tu proyecto. Lo que vamos a hacer es que cuando esta tarea se ejecute, también se ejecuten todas las demás. Vamos a llamarle watch:

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

Aquí tienes el archivo Gruntfile.js completo, sin las tareas, que usaremos en este proeycto:

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // Aquí creamos las tareas
  })
  // Cargamos los plugins de grunt
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-postcss');
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Registramos la tareas
  grunt.registerTask('default', ['watch']);
}

Configuración del Proyecto

Nuestro proyecto no pretende ser más que un ejemplo, por lo que será muy sencillo. Vamos a crear un archivo llamando index.html en cuya cabecera incluiremos los archivos css/estilos.min.css u src/scripts.min.js, compilados y minificados automáticamente por Grunt, tal y como veremos.

Vamos a crear dos archivos Sass con extensión .scss y un archivo .js que se compilarán en los archivos css/estilos.min.js y js/scripts.min.js respectivamente.

Archivos .scss

Primero crearemos los archivos .scss. Primero creamos un archivo con algunas variables al que llamaremos sass/_base.scss, sin olvidarte del guión bajo:

$font-size: 20px;
$font-color: #000000;
$max-width: 1600px;

Ahora vamos a crear un archivo .scss principal llamado sass/estilos.scss en donde importaremos el archivo anterior:

@import 'base';

main {
  max-width: $max-width;
  margin: 15px;
  color: $font-color;
  display: block;
  h1 {
    font-size: $font-size;
  }
}

Archivos .js

Vamos a crear un sencillo script que haga un alert cuando pulsemos un en botón. El archivo estará en el directorio /js y le llamaremos scripts.js:

$( document ).ready(function() {
    $('#boton').click(function() {
        alert('Has hecho clic');
    });
});

Archivo .html

Ahora vamos a crear un archivo HTML básico en la carpeta raíz de nuestro proyecto y le daremos el nombre de index.html. En este archivo simplemente agregaremos un botón, junto con los archivos minificados en la cabecera. Además también importaremos jQuery:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Tutorial de Grunt</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="css/estilos.min.css" rel="stylesheet" />
  </head>

  <body>
    <main>
      <h1>Tutorial de Grunt</h1>
      <a href="https://www.neoguias.com/grunt"> neoguias.com</a>

      <button id="boton">Pulsar aquí</button>
    </main>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.0/jquery.min.js"></script>
    <script src="js/scripts.min.js"></script>
  </body>
</html>

Tareas de Grunt

En este apartado vamos a configurar todas las tareas. Primero veremos las tareas por separado y luego el resultado final.

Especificación de tareas

Lo único que debes tener en cuenta es que el caracter comodín «*» reemplaza a cualquier tipo de cadena, permitiendo referirnos a conjuntos de archivos.

  • Tarea 'sass': El objetivo de esta tarea es que el plugin de Sass que hemos agregado una todos los archivos del directorio /sass y los compile creando un solo archivo que colocaremos en el directorio /css. Mediante la opción src definimos los archivos origen, mientras que mediante las opciones dest o dist se define el destino. En este caso hemos desactivado la creación del archivo /sourcemap:
    sass: {
      dist: {
        options: {
          sourcemap: 'none'
        },
        files: [{
          expand: true,
          cwd: 'sass',
          src: ['**/*.scss'],
          dest: 'css',
          ext: '.css'
      }]
      }
    },
  • Tareas 'postcss': Continuando con los archivos CSS, mediante esta tarea vamos a activar los prefijos vendor en los archivos CSS. Además haremos nuestro código compatible con las últimas dos versiones de los navegadores existentes:
    postcss: {
      options: {
        map: false,
        processors: [
          require('autoprefixer') ({
            browsers: ['last 2 versions']
          })
        ]
      },
      dist: {
        src: 'css/estilos.css'
      }
    },
  • Tarea 'cssmin': Finalmente vamos a minificar los archivos CSS y a guardarlos con extensión .min.css:
    cssmin: {
      target: {
        files: [{
          expand: true,
          cwd: 'css',
          src: ['*.css', '!*.min.css'],
          dest: 'css',
          ext: '.min.css'
        }]
      }
    },
  • Tarea 'uglify': Hemos llegado a la tarea en la que minificamos los archivos JavaScript y los guardamos con extensión .min.js:
    uglify: {
      build: {
        src: ['src/*.js'],
        dest: 'js/scripts.min.js'
      }
    },
  • Tarea 'watch': Finalmente aquí tenemos la tarea watch, que tal y como hemos visto es la tarea por defecto. La idea es que todas las tareas anteriores se ejecuten cuando ejecutemos esta tarea mediante la línea de comandos. Grunt estará esperando a que haya cambios en nuestros archivos .js y .css para ejecutar dichas tareas:
    watch: {
      css: {
        files: '**/*.scss',
        tasks: ['sass', 'postcss', 'cssmin']
      },
      js: {
        files: '**/*.js',
        tasks: ['uglify']
      }
    }

Archivo Gruntfile.js final

Aquí tienes el archivo Gruntfile.js final. Sí, ha sido bastante trabajo, pero lo bueno es que podrás utilizar este mismo archivo o parecido con muchos de tus proyectos, bastando con copiarlo y pegarlo:

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

    // Aquí creamos las tareas
    sass: {
      dist: {
        options: {
          sourcemap: 'none',
        },
        files: [
          {
            expand: true,
            cwd: 'sass',
            src: ['**/*.scss'],
            dest: 'css',
            ext: '.css',
          },
        ],
      },
    },
    postcss: {
      options: {
        map: false,
        processors: [
          require('autoprefixer')({
            browsers: ['last 2 versions'],
          }),
        ],
      },
      dist: {
        src: 'css/estilos.css',
      },
    },
    cssmin: {
      target: {
        files: [
          {
            expand: true,
            cwd: 'css',
            src: ['*.css', '!*.min.css'],
            dest: 'css',
            ext: '.min.css',
          },
        ],
      },
    },
    uglify: {
      build: {
        src: ['src/*.js'],
        dest: 'js/scripts.min.js',
      },
    },
    watch: {
      css: {
        files: '**/*.scss',
        tasks: ['sass', 'postcss', 'cssmin'],
      },
      js: {
        files: '**/*.js',
        tasks: ['uglify'],
      },
    },
  });

  // Cargamos los plugins de grunt
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-postcss');
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Registramos la tareas
  grunt.registerTask('default', ['watch']);
}

Ejecuta las Tareas

Y finamente vamos a proceder a ejecutar las tareas, para lo cual bastará con que ejecutes el siguiente comando:

grunt

Seguramente veas por pantalla el texto Running "watch" task y luego Waiting..., significando que la tarea watch está en ejecución y a la espera de que modifiques los archivos del proyecto. Si guardas cualquier archivo verás en la terminal que el archivo has ido modificado, junto con un log de ejecución de las tareas.

Y esto ha sido todo.


Avatar de Edu Lazaro

Edu Lázaro: Ingeniero técnico en informática, actualmente trabajo como desarrollador web y programador de videojuegos.

👋 Hola! Soy Edu, me encanta crear cosas y he redactado esta guía. Si te ha resultado útil, el mayor favor que me podrías hacer es el de compatirla en Twitter 😊

Si quieres conocer mis proyectos, sígueme en Twitter.

1 comentario en “Grunt: Qué es y Cómo se Utiliza

Deja una respuesta

“- Hey, Doc. No tenemos suficiente carretera para ir a 140/h km. - ¿Carretera? A donde vamos, no necesitaremos carreteras.”