Minificar archivos con grunt

Categories:

Antes de empezar tenemos que instalar grunt y configurar el proyecto.

¿Qué es minificar?

“La minificación de recursos se refiere a la eliminación de bytes innecesarios, como los espacios adicionales, saltos de línea y sangrías…” – vía Google Developers.

Una vez que el proyecto está configurado, lo primero que tenemos que hacer para minificar los archivos de JavaScript es instalar el plugin grunt-contrib-uglify.

$ npm install grunt-contrib-uglify --save-dev
Instalar uglify

Una vez instalado debe estar dentro de las dependencias del archivo package.json

{
  "name": "demo",
  "version": "0.1.0",
  "private": "true",
  "description": "Crear un paquete json para utilizar grunt",
  "main": "index.html",
  "author": "eamexicano",
  "license": "MIT",
  "devDependencies": {
    "grunt": "^0.4.5",
    "grunt-contrib-concat": "^0.5.0"
  }
}

Ahora tenemos que realizar tres modificaciones en el archivo Grunfile.js para poder minificar los archivos.

  1. Configurar la tarea – uglify -.
  2. Cargar el plugin que tiene la tarea a utilizar – uglify -.
  3. Registrar la tarea.
module.exports = function(grunt) {

  grunt.initConfig({ 
    uglify: {
      
    }
  });

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

  grunt.registerTask("default", ['uglify']);
};

En el ejemplo anterior las tareas dos – grunt.loadNpmTasks(‘grunt-contrib-uglify’) – y tres – grunt.registerTask(“default”, [‘uglify’]); – ya están hechas.

La configuración de la tarea se realiza dentro de la propiedad uglify – uglify: {} -.

Las opciones de configuración que vamos a revisar son:

  1. Compression: Comprimir el tamaño de los archivos.
  2. Manging: Cambiar el nombre de las variables.
  3. Beautification: Volver el código a un formato legible.
  4. Banner: Agrega el banner al principio del archivo generado.
  5. sourceMap: Crea un mapa del código fuente para el momento de depurar el código.

Compression

Dentro de uglify vamos a especificar que una de las opciones que queremos es comprimir los archivos.

options: {
 compress: true
},

Para poder comprimir los archivos tenemos que indicar de qué archivos se va a tomar el contenido y qué archivo es el que se va a generar.

Los archivos de origen los podemos especificar dentro de un arreglo, separados por comas.

js: {
  src: ["js/demo01.js", "js/demo02.js"],       
  dest: "js/demo.js"
}

O podemos especificar que lea todos los archivos con extensión js a excepción de uno – demo.js – que es el archivo que va a contener el código comprimido.

js: {
  src: ["js/*.js", "!js/demo.js"],
  dest: "js/demo.js"
}

Para ejecutar la tarea podemos:

  1. Utilizar el comando grunt porque la tarea uglify está definida como predeterminada
  2. Utilizar el comando grunt y el nombre de la tarea – uglify –
  3. Utilizar el comando grunt, el nombre de la tareas y utilizar el parámetro js para especificar los archivos que se van a comprimir.
$ grunt

$ grunt uglify

$ grunt uglify:js
Ejecutar uglify

Si revisamos el archivo generado – demo.js – los archivos demo01.js y demo02.js están concatenados en una sola línea. Además la variable local “mensaje” dentro de “visualizar_contenido” en demo01.js se sustituyó por “a” en demo.js

function visualizar_contenido(){var a;a=titulo.textContent,alert(a)}function actualizar_contenido(){parrafo.textContent=prompt("¿Nuevo contenido para el párrafo?")}var titulo=document.getElementsByTagName("h1")[0];titulo.addEventListener("click",visualizar_contenido);var parrafo=document.getElementsByTagName("p")[0];parrafo.addEventListener("click",actualizar_contenido);

Manging

El concepto de manging se refiere a cambiar el nombre de las variables por un nombre más corto con la finalidad de reducir un poco más el tamaño del archivo. Si queremos evitar esto tenemos que deshabilitar la opción mangle dentro de las tareas de uglify.

options: {
  compress: true,
  mangle: false
},

Al deshabilitar la opción mangle no se modifica el nombre de las variables.
El código anterior quedaría así:

function visualizar_contenido(){var mensaje;mensaje=titulo.textContent,alert(mensaje)}function actualizar_contenido(){parrafo.textContent=prompt("¿Nuevo contenido para el párrafo?")}var titulo=document.getElementsByTagName("h1")[0];titulo.addEventListener("click",visualizar_contenido);var parrafo=document.getElementsByTagName("p")[0];parrafo.addEventListener("click",actu

Si queremos habilitar esta opción es conveniente habilitarla de manera explícita para que no quede lugar a dudas.

options: {
  compress: true,
  mangle: true
},

Beautification

El concepto de embellecimiento – beautification – se refiere a expandir el código que se encuentra minificado para que sea legible.
Si hubo cambio en el nombre de las variables, el embellecimiento no las va a cambiar.

options: {
  compress: true,
   mangle: true,
   beautify: true
},

Ésta opción viene deshabilitada de manera predeterminada porque su función es tomar un código minificado y lo intenta presentar de manera legible. Agrega saltos de línea y el código dentro de las funciones les agrega tabulaciones.

function visualizar_contenido() {
    var a;
    a = titulo.textContent, alert(a);
}

function actualizar_contenido() {
    parrafo.textContent = prompt("¿Nuevo contenido para el párrafo?");
}

var titulo = document.getElementsByTagName("h1")[0];

titulo.addEventListener("click", visualizar_contenido);

var parrafo = document.getElementsByTagName("p")[0];

parrafo.addEventListener("click", actualizar_contenido);

Banner

Esta opción permite agregar una línea de texto al principio de los archivos a minificar.

options: {
        compress: true,
        mangle: false,
        beautify: false,
        banner: "/* Mi app 2014 */",
      },

En este caso se va a incluir el comentario – /* Mi app 2014 */ – antes de incluir el código en el archivo minificado.

Puede parecer que no tiene mucho sentido pero dentro de las opciones podemos incluir código que se va a interpretar dinámicamente. En el siguiente caso se muestra la fecha y hora de creación si nos interesa conocer la versión del código que está utilizando en un momento determinado.

options: {
        compress: true,
        mangle: false,
        beautify: false,
        banner: "/* Creado: <%= grunt.template.today('yyyy-mm-dd hh:mm:ss') %> */",
      },

sourceMap

Esta opción genera un mapa desde el archivo comprimido hacia los archivos que se utilizaron para comprimirlo.

El valor que acepta es true.

options: {
        compress: true,
        mangle: false,
        beautify: false,
        banner: "/* Creado: <%= grunt.template.today('yyyy-mm-dd hh:mm:ss') %> */",
        sourceMap: true
      },

Una vez que se establece la propiedad y se minifican los archivos de crea un archivo con el nombre del archivo comprimido pero con la extensión map – demo.js.map – dentro de la misma carpeta donde está el archivo comprimido.

El contenido del archivo es el siguiente:

{"version":3,"file":"demo.js","sources":["demo01.js","demo02.js"],"names":["visualizar_contenido","mensaje","titulo","textContent","alert","actualizar_contenido","parrafo","prompt","document","getElementsByTagName","addEventListener"],"mappings":";AAEA,QAASA,wBACP,GAAIC,QACJA,SAAUC,OAAOC,YACjBC,MAAMH,SCHR,QAASI,wBACPC,QAAQH,YAAcI,OAAO,qCDH/B,GAAIL,QAASM,SAASC,qBAAqB,MAAM,EAQjDP,QAAOQ,iBAAiB,QAASV,qBCRjC,IAAIM,SAAUE,SAASC,qBAAqB,KAAK,EAMjDH,SAAQI,iBAAiB,QAASL"}

Referencia de uso de un sourcemap.

Si tu navegador no es compatible con la etiqueta de video o tuviste algún problema para visualizar el video existe una versión en YouTube

Aquí está el archivo con el demo-grunt-uglify para descargar.

Las carpetas que se utilizaron para esta versión fueron:

  1. demo-07: Package json con la dependencia grunt-contrib-uglify incluida.
  2. demo-08: Configuración del archivo Gruntfile.js

* Se necesitan instalar las dependencias con

$ npm install