Optimizando con Gulp

Ivan Martil

Si no me fallan los cálculos este es el cuarto artículo de Gulp que escribo. Echadle un ojo a los artículos anteriores si queréis ver de donde venimos. Hoy toca hablar de cómo optimizar la salida de nuestros archivos. La idea siempre es lograr el mínimo número de peticiones al servidor y reducir el peso de los archivos lo máximo posible. Para ello vamos primero a trabajar nuestro archivo css.

Hasta el momento ya hemos reunido todo nuestros estilos en style.css. El siguiente paso es comprimir y minificar ese archivo.

Gulp Cssnano

En Cssnano encontramos un plugin multitarea. Aglutina diferentes módulos PostCss para optimizar el código de nuestros estilos. Es totalmente configurable y va mucho más allá que la simple minificación de archivos. Es escalable pudiendo activar o desactivar los módulos a nuestro antojo. Existen más de 20 módulos dentro de cssnano para optimizar nuestro css. Algunos de ellos son:

Postcss-discard-comments

Elimina los comentarios de nuestros archivos.

Postcss-discard-empty

En el caso de encontrar reglas vacías las elimina.

Postcss-discard-duplicates

Elimina las reglas y declaraciones duplicadas.

Postcss-merge-rules

Unifica las reglas para reducir peso

Autoprefixer

Elimina los prefijos css de nuestro flujo de trabajo. Él añade los prefijos según nuestras indicaciones.

Veamos cómo funciona. Lo instalamos npm install gulp-cssnano --save-dev y añadimos la dependencia en nuestro gulpfile.js var cssnano = require('gulp-cssnano');

Tenemos que modificar nuestra tarea sass para incluir a cssnano


//variables
var input="./src/scss/style.scss";
var output="./dist/css";

gulp.task('sass', function(){ 
  return gulp 
  .src(input) 
  .pipe(sourcemaps.init()) 
  .pipe(sass().on('error', sass.logError)) 
  .pipe(cssnano()) 
  .pipe(sourcemaps.write('./maps')) 
  .pipe(gulp.dest(output)) 
  .pipe(browserSync.stream());
});

El plugin realiza de forma predeterminada  la máxima optimización posible. Pero podemos desactivar los módulos indeseados.


.pipe(cssnano({
  zindex:false,
  discardComments:false,
  mergeRules:false
}))

Como vemos en el ejemplo simplemente con un booleano podemos activar o desactivar los módulos. No describiré aquí la lista entera de módulos que podemos controlar ni sus funciones. En la documentación encontrareis detalladamente cada una de sus propiedades. Pero si le prestaré atención al módulo autoprefixer.

Mi tema base estaba lleno de mixins con prefijos para añadir propiedades como transform o filter . Este plugin elimina de golpe la necesidad de los mixins para prefijos. Lo configuramos hasta donde queremos dar soporte y él se encarga de incluir los prefijos. No solo es cómodo, sino que nos ahorra poner prefijos cuando el navegador ya los acepta. A la velocidad que se actualizan y mejoran los navegadores es difícil mantenerse informado sobre aquellos prefijos necesarios y los que no.

Su configuración con cssnano me ha dado algún que otro problema. Según la documentación este viene activado por defecto. Pero en mi caso parece que no es así (la versión del plugin para el artículo es la 2.1.1).


//variable para soporte autoprefixer
var soporteAp =[
    'last 2 versions',
    'android 4',
    'ie >=10'
];

.pipe(cssnano({
  zindex:false,
  discardComments:false,
  mergeRules:false,
  autoprefixer:{browser:soporteAp, add:true}
}))

En el código vemos cómo he creado una variable para añadir las opciones de soporte para navegadores. Podemos añadir navegadores de manera explícita o por estadísticas de uso. En Browserlist encontramos las palabras clave para añadir soporte en autoprefixer. En el ejemplo:

last 2 versions

hace referencia a las últimas dos versiones de los navegadores ‘principales’.

  • chrome
  • firefox
  • explorer
  • edge
  • ios
  • opera
  • safari
  • ExplorerMobile

android 4

De manera explícita citamos un navegador concreto.

ie>=10

Indicamos que en el caso de explorer necesitamos soporte de explorer 10 hacia adelante. Lo incluye cualquier versión de explorer posterior a la 10.

La opción que añado despues del soporte add:true debería ,según la documentación, estar activa por defecto. En mi caso solo funciona pasando el valor true.

Nuestro css esta minificado y optimizado. Pero algo que echaba a faltar de mixture eran las notificaciones. Cuando algo no funciona correctamente recibimos el aviso en el terminal y no acaba de ser todo lo cómodo que me gustaría.

Gulp Notify

La idea es evitar mirar el terminal para ver si todo está funcionando o si existe algún error de css en sass. En mi caso es bastante habitual que tenga el terminal minimizado y sólo sublime y un navegador estén siempre a la vista. Notify se encargará de vigilar por nosotros.

Lo instalamos npm install gulp-notify --save-dev y creamos la dependencia var notify = require('gulp-notify');

En la documentación encontramos una api detallada con diferentes métodos para interactuar con el plugin. Veamos como modificar nuestra tarea sass para añadir las notificaciones.


//variables
var input="./src/scss/style.scss";
var output="./dist/css";
var soporteAp =[
    'last 2 versions',
    'android 4',
    'ie >=10'
];

//tarea sass
gulp.task('sass', function(){ 
  return gulp 
  .src(input) 
  .pipe(sourcemaps.init()) 
  .pipe(sass().on('error',notify.onError({
     message:'Error: <%= error.message %>',
     title:'Fallo en sass'
  }))) 
  .pipe(cssnano()) 
  .pipe(sourcemaps.write('./maps')) 
  .pipe(gulp.dest(output)) 
  .pipe(browserSync.stream());
  .pipe(notify({
    message:"Css actualizado",
    title: 'Todo ok'
  }))
});

imagen 1
imagen 1

En la documentación encontrareis que existen múltiples formas de usar notify y pasarle nuestras opciones de configuración. No solo podemos personalizar los mensajes, el logo o incluso el sonido de la notificación son parámetros configurables. Llamémosle pereza o practicidad, pero a mi me basta con una simple aviso informativo. En el ejemplo empleamos en dos ocasiones a notify. En notify.onError configuramos el mensaje y el título de la notificación. Añadiendo error.message logramos que el plugin recoja información sobre el error y nos diga cual es y dónde está. Como última instrucción de nuestra tarea añadimos a notify en un pipe() para que nos comunique que ha finalizado toda la tarea sin problemas. En la imagen 1 podemos ver las notificaciones de mac. En el caso de error vemos como nos informa  en que archivo esta el error y cual es el problema. En windows, en mi caso windows 10, si tenemos las notificaciones activas (configuración/sistema/notificaciones) el funcionamiento es idéntico. Tan solo varía el aspecto de las notificaciones que son propias de cada sistema operativo.

Por el momento doy por configurado gulp para el desarrollo con sass. Estoy bastante satisfecho con él, ya tengo claro que no vuelvo a mixture ni nada por el estilo. Me falta minificar y concatenar javascript junto con algún que otro detalle, pero pronto indagaré sobre ello.

Comentarios 2

Opina libremente

Tu dirección de correo electrónico no será publicada.Todos los campos son obligatorios.

  • Andres

    esperando mas... gracias

    • imm

      Gracias a ti por escribir.