miércoles, marzo 26, 2014

GulpJS amistoso con AngularJS

Hace poco después de mi lectura diaria descubrí GulpJS. Es una simpática herramienta de línea de comando que permite optimizar muchas cosas del desarrollo web, desde la minimización de imágenes, hasta la "liposucción de código" como le llamamos en la oficina al proceso de eliminar comentarios y mensajes de debug.
El resultado normalmente es un archivo .js minimizado, un archivo .css también minimizado, e imágenes y archivos .html "optimizados".

No les voy a enseñar a usarlo, eso lo pueden ver en detalle en los siguientes enlaces (todos en inglés):
Los primeros problemas a los que me enfrenté fueron básicamente que las configuraciones por defecto son muy agresivas, por lo que mis HTMLs quedaron sin algunos atributos necesarios para que mis controladores Angular funcionaran, y que derechamente mis controladores Angular dejaron de funcionar.

Después de leer algo de documentación para revisar las opciones de los plugins de Gulp que decidí usar, y trás algunas pruebas, llegué al siguiente código, que me ha arrojado los mejores resultados:

// Include gulp
var gulp = require('gulp'); 

// Include Our Plugins
var jshint = require('gulp-jshint');
var concat = require('gulp-concat');
var changed = require('gulp-changed');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var stripDebug = require('gulp-strip-debug');

// Lint Task
gulp.task('lint', function() {
    return gulp.src('js/*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'));
});

// Concatenate & Minify JS
gulp.task('scripts', function() {
    return gulp.src(['js/angular.min.js', 'js/Directive/bindonce.min.js', 'js/jquery-2.0.3.min.js', 'js/bootstrap.min.js',  'js/app.js', 'js/*.js', 'js/Service/*.js', 'js/Filter/*.js', 'js/Directive/*.js', 'js/Controller/*.js'])
        .pipe(concat('appjs.js'))
        .pipe(stripDebug())
        .pipe(gulp.dest('dist'))
        .pipe(rename('app.min.js'))
        .pipe(uglify({ mangle: false }))
        .pipe(gulp.dest('dist'));
});

// include plug-ins
var minifyHTML = require('gulp-minify-html');
 
// minify new or changed HTML pages
gulp.task('htmlpage', function() {
  var htmlSrc = '*.html',
      htmlDst = 'dist';
 
  gulp.src(htmlSrc)
    .pipe(changed(htmlDst))
    .pipe(minifyHTML({ empty: true, spare:true, quotes: true }))
    .pipe(gulp.dest(htmlDst));
});

// include plug-ins
var autoprefix = require('gulp-autoprefixer');
var minifyCSS = require('gulp-minify-css');
 
// CSS concat, auto-prefix and minify
gulp.task('styles', function() {
  gulp.src(['css/bootstrap.min.css', 'css/*.css'])
    .pipe(concat('styles.min.css'))
    .pipe(autoprefix('last 2 versions'))
    .pipe(minifyCSS())
    .pipe(gulp.dest('dist'));
});

// default gulp task
gulp.task('default', ['htmlpage', 'scripts', 'styles'], function() {
});

Lo único que no pude resolver a través de parámetros (y si alguien lo sabe se agradece si comparten el dato) fue el hecho que el plugin minify-html se "come" mis espacios en blanco intencionales (a veces necesarios) y los atributos que no tienen valor (como el bindonce). Tan grave no es si sabes donde ponerlos de vuelta, pero eso ya es parte del trabajo manual.