grunt

Utilizar Grunt para automatizar procesos

Grunt es un task runner de JavaScript, una herramienta utilizada para realizar automáticamente tareas frecuentes como minificación, compilación, pruebas unitarias y linting.

Utiliza una interfaz de línea de comandos para ejecutar tareas personalizadas definidas en un archivo (conocido como Gruntfile). Grunt se distribuye a través de npm y cuenta con multitud de complementos disponibles.

Antes de empezar, conviene actualizar NPM (Libreria de software, instalador y gestor de paquetes), con el comando:

npm update -g npm

Instalamos el CLI (Command Line Interface) de grunt de forma global:

npm install -g grunt-cli

Nos desplazamos a la carpeta del proyecto (p.e. cd [nombre-del-proyecto]), desde done preparamos el proyecto Grunt, creando el fichero package.json, mediante el comando:

npm init -y

Despues instalamos Grunt, generando las dependencias:

npm install grunt --save-dev

En este punto, podemos instalar los complementos (tareas) que queremos utilizar en nuestro proyecto, podemos instalar las siguientes, dependiento que tareas queremos utilizar:

  • Eliminar ficheros y carpetas:
    npm install grunt-contrib-clean –save-dev
  • Concatenar ficheros:
    npm install grunt-contrib-concat –save-dev
  • Comprimir ficheros CSS:
    npm install grunt-contrib-cssmin –save-dev
  • Compilar ficheros Sass a CSS:
    npm install grunt-contrib-sass –save-dev
  • Minificar ficheros JavaScript:
    npm install grunt-contrib-uglify –save-dev
  • Ejecutar tareas predeterminadas cuando se añaden, modifican o eliminan determinados ficheros:
    npm install grunt-contrib-watch –save-dev
  • Minificar imágenes de formato PNG, JPEG, GIF y SVG:
    npm install grunt-contrib-imagemin –save-dev
  • Validar ficheros con JSHint:
    npm install grunt-contrib-jshint –save-dev
  • Copiar ficheros:
    npm install grunt-contrib-copy –save-dev
  • Prefijar ficheros CSS:
    npm install grunt-autoprefixer –save-dev
  • Transferir ficheros usando FTP:
    npm install grunt-ftp-push –save-dev
  • Sincronizar el explorador:
    npm install grunt-browser-sync –save-dev

Ahora queda definir en el fichero Gruntfile.js las tareas concretas. En este fichero tenemos por una parte las tareas (grunt.initConfig), la carga de los complementos (grunt.loadNPMTasks) y el registro de tareas (grunt.registerTask).

module.exports = function(grunt) {
  grunt.initConfig({
    sass: {
      dev: {
        files: {
          'src/style.css': 'src/sass/style.scss'
        }
      },
      dist: {
        options: {
          style: 'compressed',
          sourcemap: 'none'
        },
        files: [{
          expand: true,
          cwd: 'src/sass',
          src: ['.scss'],
          dest: 'src',
          ext: '.css'
        }]
      }
    },
    autoprefixer: {
      options: {
        browsers: ['last 2 version','ie 10'],
        grid: true
      },
      dist: {
        files: [{
            expand: true,
            cwd: 'src',
            src: 'style.css',
            dest: 'src',
            ext: '.pre.css'
        }]
      }
    },
    cssmin: {
      dist: {
        src: 'src/style.pre.css',
        dest: 'dist/style.css'
      }
    },
    clean: {
      dist: {
        src: ['dist/']
      },
      uploads: {
        src: ['dist-uploads/']
      }
    },
    concat: {
      options: {
        separator: ';',
      },
      js: {
        src: ['src/js/.js','!src/js/built.js'],
        dest: 'src/js/built.js'
      }
    },
    uglify: {
      dist: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: 'js/.js',
          dest: 'dist/',
        }]
      }
    },
    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: 'src/',
          src: ['/.{png,jpg,gif,svg}'],
          dest: 'dist/'
        }]
      },
      uploads: {
        files: [{
          expand: true,
          cwd: 'uploads/',
          src: ['/.{png,jpg,gif,svg}'],
          dest: 'dist-uploads/'
        }]
      }
    },
    copy: {
      dist: {
        expand: true,
        cwd: 'src/',
        src: ['/.php'],
        dest: 'dist/'
      },
      style: {
        expand: true,
        cwd: 'src/',
        src: ['style.css'],
        dest: 'dist/'
      },
      localhost: {
        expand: true,
        cwd: 'dist/',
        src: ['/'],
        dest: 'c:/xampp/htdocs/wordpress/wp-content/themes/proyecto/'
      }
    },
    ftp_push: {
      options: {
        host: 'ftp.proyecto.com',
        username: 'user',
        password: 'pass',
        dest: 'proyecto',
      },
      dist: {
        files: [{
          expand: true,
          cwd: 'dist/',
          src: ['/'],
          dest:'wp-content/themes/proyecto/'
        }]
      },
      uploads: {
        files: [{
          expand: true,
          cwd: 'dist-uploads/',
          src: ['/'],
          dest:'wp-content/uploads/'
        }]
      }
    },
    browserSync: {
      dev: {
          bsFiles: {
            src : ['c:/xampp/htdocs/wordpress/wp-content/themes/proyecto//']
          },
          options: {
            watchTask: true,
            proxy: 'localhost/proyecto',
          }
      }
    },
    jshint: {
      dev: ['src/js/.js']
    },
    watch: {
      options: {
        livereload: true
      },
      sass: {
        files: ['src/sass/style.scss'],
        tasks: ['sass:dev']
      },
      diststyle: {
        files: ['src/style.css'],
        tasks: ['clean:dist','copy:style','copy:localhost']
      },
      js: {
        files: ['src/js/.js'],
        tasks: ['jshint:dev']
      }
    },
  });

  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-imagemin');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-browser-sync');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-ftp-push');
  grunt.loadNpmTasks('grunt-autoprefixer');
  
  grunt.registerTask('default',['browserSync:dev','watch:sass','watch:diststyle']);
  
  grunt.registerTask('distribute',[
    'clean:dist',
    'autoprefixer:dist',
    'cssmin:dist',
    'uglify:dist',
    'imagemin:dist',
    'copy:dist'
    ]);

  grunt.registerTask('pushweb',['ftp_push:dist']);

  grunt.registerTask('pushuploads',['clean:uploads','imagemin:uploads','ftp_push:uploads']);

  grunt.registerTask('pushlocal', ['copy:localhost']);

};

Para ejecutar una tarea (p.e., distribute):

grunt distribute

En este caso, esta tarea realiza lo siguiente:

  1. Elimina los ficheros de la carpeta dist.
  2. Autoprefija el fichero CSS style.css de la carpeta src, generando el fichero style.pre.css.
  3. Minimiza el fichero style.pre.css, generando el fichero style.css en la carpeta dist.
  4. Minimiza los archivos js de la carpeta src/js a la carpeta dist/js.
  5. Minimiza los archivos de imagen de formatos png, jpg, gif y svg de la carpeta src y sus subcarpetas a la carpeta dist.
  6. Copia los ficheros de la carpeta dist a la carpeta de nuestro proyecto c:/xampp/htdocs/wordpress/wp-content/themes/proyecto/.

Si ejecutamos grunt, se cargaran las tareas por defecto (default), que en este caso carga el sincronizador del explorador y el observador (watch), que compila los ficheros Sass a CSS.

Si queremos ejecutar una tarea concreta, por ejemplo, subir nuestro proyecto local a nuestro servidor web (p.e., ftp.proyecto.com), ejecutamos:

grunt pushweb

Si queremos que la tarea de compilación se realice siempre que se observen cambios en los ficheros Sass, ejecutamos el comando:

grunt watch:sass

en el que hemos indicado la tarea y su target específico a ejecutar.

Si queremos vaciar la carpeta dist-uploads:

grunt clean:uploads

Si queremos minimizar las imágenes de la carpeta uploads y pasarlas a la carpeta dist-uploads:

grunt imagemin:uploads

Modificando el fichero Gruntfile.js podemos generar nuevas tareas, redefinirlas y adaptarlas a nuestro proyecto en concreto, con lo que automatizar tareas repetitivas que realizamos durante el desarrollo del proyecto, ahorrando tiempo y mejorando la productividad.

En Doowebs podemos ayudarte con el desarrollo web, contáctanos para solicitar más información sobre nuestros servicios.