Mi Gruntfile, de momento

Desde hace un tiempo vengo usando Grunt para cualquier proyecto que empiezo (o cualquiera que pueda adaptar), Grunt es un gestor de tareas que permite automatizar cosas como compilar los archivos sass, optimizar imágenes, añadir prefijos para los navegadores, ... Básicamente cualquier tarea repetitiva necesaria en el desarrollo frontend.

Hay muchas guías de iniciación a Grunt y esto no pretende ser una más, simplemente quería dejar constancia de como es mi Gruntfile actualmente para futuras referencias. Tampoco es un paso a paso, si no sabes ya que es un plugin de Grunt o como se instala, este no es tu artículo. Puedes empezar con la documentación oficial, en inglés, o buscar en tu buscador favorito alguna guía de las miles que hay por ahí.

El archivo real es algo más grande, pero en su forma básica y siempre hablando de desarrollo (las tareas de puesta en producción son algo más complejas) sería así (la explicación a continuación):

module.exports = function(grunt) {
  require('time-grunt')(grunt);
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    sass: {
      options: {
        sourceMap: true
      },
      dist: {
        files: {
          'public/css/master.css' : 'app/sass/master.scss',
          'public/css/admin.css' : 'app/sass/admin.scss'
        }
      }
    },
    watch: {
      css: {
        files: '**/*.scss',
        tasks: ['sass', 'newer:autoprefixer:no_dest']
      }
    },
    autoprefixer: {
      no_dest: {
        src: ['public/css/*.css']
      }
    },
    browserSync: {
      dev: {
        bsFiles: {
          src : ['public/css/*.css', 'app/templates/**/*.mustache']
        },
        options: {
          watchTask: true,
          proxy: 'local.dev'
        }
      }
    }
  });
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-autoprefixer');
  grunt.loadNpmTasks('grunt-newer');
  grunt.loadNpmTasks('grunt-browser-sync');
  grunt.registerTask('default',['browserSync', 'watch']);
};

Primero, un repaso a los plugins que utilizo:

  • time-grunt: no tiene más utilidad que mostrar estadísticas de tiempos de lo que cuesta realizar cada tarea.
  • grunt-sass: es un compilador de Sass que utiliza LibSass en lugar de la implementación de Ruby y que a pesar de no ser 100% compatible con las versiones más modernas de Sass es extremadamente rápida, insisto, extremadamente.
  • grunt-contrib-watch: sirve para monitorizar cuando cambian los archivos y realizar tareas cuando esto pase.
  • grunt-autoprefixer: Autoprefixr utiliza los datos de Can I Use para automáticamente añadir los prefijos correspondientes para cada navegador (adiós a mi único motivo real para usar compass, yihaaa).
  • grunt-newer: permite realizar las tareas sólo a los archivos que hayan cambiado, esto es muy útil cuando se realizan tareas de optimización de imágenes, por ejemplo.
  • grunt-browser-sync: mi último añadido a mi caja de trucos, es una joya, adiós a livereload entre otras cosas, y como es lo único diferente a lo que se suele ver por ahí, voy a explicar un poco más.

BrowserSync es un servidor sobre Node que permite, entre otras muchas cosas, conectar a distintos dispositivos de la misma red a la misma página, registra las interacciones que se realizan y replica las acciones en cada dispositivo conectado, mola.

Tiene otras cosas interesantes, en mi caso son dos: permite utilizar tu propio servidor backend y permite inyectar el código CSS (que era una cosa que había perdido al pasarme a Grunt y es mucho mejor que recargar la página completa).

La configuración en mi caso es muy sencilla:

browserSync: {
  dev: {
    bsFiles: {
      // Archivos a controlar, esto es: el CSS y las plantillas de la aplicación
      src : ['public/css/*.css', 'app/templates/**/*.mustache']
    },
    options: {
      // Imprescindible para permitir seguir utilizando watch (en mi caso, compilar sass)
      watchTask: true,
      // El nombre de mi vhost, así puedo seguir usando PHP
      proxy: 'local.dev'
    }
  }
}

Una vez registrada la tarea, al ejecutar grunt crea un wrapper alrededor de mi vhost y me abre en el navegador la página de mi proyecto. Además me proporciona una dirección desde la cual se pueden conectar más dispositivos a ella.

En la documentación está explicado todo lo que puede hacer.

Una vez que le coges el gusanillo a Grunt, es imprescindible este artículo de Addy Osmani sobre optimización de Grunt.