Compilando los ficheros Sass de Magento utilizando Gulp y Node-sass

Sass

Antes de todo dar las gracias a Damián por invitarme a escribir en su blog, es un honor escribir en un blog del que hemos aprendido tanto, espero estar a la altura.

Desde la versión 1.9.0.0 de Magento se nos introdujo de forma nativa en los themes Sass con el famoso theme rwd. Trabajando como Freelance, me he encontrado con infinidad de proyectos en los que tocan directamente el css sin compilar los SCSS, lo que lleva a una perdida de tiempo y a unos buenos dolores de cabeza cuando el proyecto lo toca otra persona.

Para simplificar todo el proceso de compilación de los ficheros Sass a los css, después de muchos dolores de cabeza con Ruby, me decanté hace tiempo en hacerlo con Node.js.

Usaremos pues Node.js, Gulp y Bower. Tendremos que usar solamente comandos muy básicos de command-line (Terminal en OSX, Command Prompt en Windows, …), con lo que no implicará mucha dificultad.

Instalando Node.js

Lo primero que necesitaremos antes de todo será instalar Node.js, para ello sólo tendremos que ir a http://nodejs.org y descargar la versión compatible con nuestro sistema operativo. Hay un botón gigante que pone Download for … con lo que no tiene perdida.

Una vez instalado, procederemos a instalar Bower.

Instalando Bower y Gulp

Bower es un Gestor de paquetes muy simple que nos ayudará a instalar algunas dependencias para el proyecto, requiere tener instalado node, npm (el gestor de paquetes de node que se instala automáticamente) y git (si no usáis git, podéis dejar de leer en este punto y cerrar la pestaña del navegador, sois unos locos y no sabré como explicaros nada más), para instalarlo sólo tendremos que poner en la Command-line:

npm install -g bower

Si encontráis algún problema visitad la web de Bower y seguro que encontráis la solución.

Más adelante entenderéis para que lo usamos.

Después instalaremos Gulp, que es el task manager que usaremos. Nos ayudará a hacer tareas de forma sencilla, programándolas para luego reutilizarlas.

Lo instalaremos poniendo:

npm install -g gulp

Empezando el proyecto e instalando dependencias

En la command-line debemos de posicionarnos en el directorio del proyecto y una vez dentro ejecutar el siguiente comando:

npm init

Esto nos creará un fichero package.json con la información que pusimos al ejecutar el comando. Ahora añadiremos las dependencias:

npm install gulp gulp-sass gulp-autoprefixer gulp-notify browser-sync --save-dev

Eso instalará las dependencias localmente y las guardará en el fichero package.json que creamos anteriormente, lo que nos ayudará a su instalación en otros entornos o la actualización de las dependencias.

Llegados a este punto, tendréis en la raíz del proyecto un directorio llamado node_modules que incluye todos los ficheros de las dependencias. Mi recomendación es que añadáis este directorio al .gitignore del proyecto y que si otro usuario tiene que trabajar con Gulp, sólo tenga que instalar las dependencias desde la versión que contenga el package.json. Lo que yo tengo en mi .gitignore es:

node_modules

Creando nuestro gulpfile

Una vez instalado node, gulp y las dependencias del proyecto, sólo nos quedaría crear un fichero llamado gulpfile.js en la raíz y añadir nuestras tareas.

Pero antes, os voy a contar uno de los grandes problemas de utilizar el compilador de node-sass. El theme RWD de Magento, está creado usando Compass, un framework de Sass, pero sólo tenemos la versión en Ruby de Compass, con lo que de normal tendríamos que recurrir a las gemas de sass y compass para hacerlo funcionar correctamente, algo que para mí lo hace más lento.

La alternativa que os propongo es instalar todos los mixins de Compass en el proyecto e incluirlos a la hora de compilar, lo que hará que no tengamos ningún tipo de fallo al compilar.

Sólo tenéis que poner el siguiente comando:

bower install https://github.com/perichus/compass-mixins.git#master

Es un fork del proyecto original de Guillaume Balaine https://github.com/Igosuki/compass-mixins.

Ahora sí, ¡vamos a crear nuestro gulpfile y añadir las tareas!

gulpfile.js

'use strict';
 
var gulp         = require('gulp');
 
// Gulp Plugins
var sass         = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var browserSync  = require('browser-sync');
var notify       = require('gulp-notify');
 
// Magento Settings
var magento = {};
 
magento.name = 'RWD'; // Define the project name
magento.pkg = 'rwd'; // Define your package
magento.theme = 'default'; // Define your theme
magento.domain = 'local.magento.com'; // Define your domain
 
magento.skin = './skin/frontend/';
magento.src = magento.skin + magento.pkg + '/' + magento.theme + '/scss/**/*.scss';
magento.dest = magento.skin + magento.pkg + '/' + magento.theme + '/css/';
 
gulp.task('sync', function() {
    browserSync.init([
        magento.dest + '*.css'
    ], {
        host: magento.domain,
        proxy: magento.domain,
        ui: false,
        open: false
    });
});
 
gulp.task('sass', function() {
    return gulp.src(magento.src)
        .pipe(sass({includePaths: 'bower_components/compass-mixins/lib',
            outputStyle: 'expanded'}).on('error', sass.logError))
        .pipe(autoprefixer({ browsers: ['last 2 version', 'safari 5', 'ie >= 9'] }))
        .pipe(gulp.dest(magento.dest))
        .pipe(browserSync.reload({stream: true}))
        .pipe(notify({message: magento.name + ' compiled successfully', onLast: true}));
});
 
gulp.task('watch', ['sync'], function() {
    gulp.watch(magento.src, ['sass']);
});
 
gulp.task('default', ['sass', 'watch']);

Voy a partir el fichero en varias partes y os voy explicando cada una de ellas:

Gulp y Plugins

'use strict';
 
var gulp         = require('gulp');
 
// Gulp Plugins
var sass         = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var browserSync  = require('browser-sync');
var notify       = require('gulp-notify');

Aquí se define gulp y todos los plugins que usaremos posteriormente en las tareas. Las tareas que vamos a tener serán: sass, sync, watch y default.

Configuración sobre Magento

// Magento Settings
var magento = {};
 
magento.name = 'RWD'; // Define the project name
magento.pkg = 'rwd'; // Define your package
magento.theme = 'default'; // Define your theme
magento.domain = 'local.magento.com'; // Define your domain
 
magento.skin = './skin/frontend/';
magento.src = magento.skin + magento.pkg + '/' + magento.theme + '/scss/**/*.scss';
magento.dest = magento.skin + magento.pkg + '/' + magento.theme + '/css/';

Aquí configuramos los distintos aspectos de nuestro magento, como el nombre del proyecto, el package, el theme o el dominio en el que estamos trabajando.

BrowserSync

gulp.task('sync', function() {
    browserSync.init([
        magento.dest + '*.css'
    ], {
        host: magento.domain,
        proxy: magento.domain,
        ui: false,
        open: false
    });
});

Este plugin es maravilloso, lo que hará es refrescarnos el navegador con los cambios de css cada vez que guardemos un cambio sin necesidad de instalar ningún fichero en el magento, solo tendremos que añadir el puerto que nos indique la command-line una vez iniciemos la tarea (por ejemplo: http://local.magento.com:3000). ¡Nos ahorrará infinidad de recargas!

Sass

gulp.task('sass', function() {
    return gulp.src(magento.src)
        .pipe(sass({includePaths: 'bower_components/compass-mixins/lib',
            outputStyle: 'expanded'}).on('error', sass.logError))
        .pipe(autoprefixer({ browsers: ['last 2 version', 'safari 5', 'ie >= 9'] }))
        .pipe(gulp.dest(magento.dest))
        .pipe(browserSync.reload({stream: true}))
        .pipe(notify({message: magento.name + ' compiled successfully', onLast: true}));
});

La joya de la corona, con esta tarea le indicamos donde están los ficheros SCSS, le incluimos los mixins de Compass, compila los SCSS en ficheros CSS, le añadimos autoprefixer (un plugin que añade/quita los vendor prefixes usando los valores de Can I Use. ¡Super útil!) y recarga en BrowserSync los ficheros CSS modificados.

Watch

gulp.task('watch', ['sync'], function() {
    gulp.watch(magento.src, ['sass']);
});

Con esta tarea definimos las tareas que se ejecutarán cuando se hagan cambios en ciertos ficheros.

Default

gulp.task('default', ['sass', 'watch']);

Esta es la tarea que se ejecuta por defecto al ejecutar el comando de gulp.

Con esto sólo nos quedaría ejecutar en la command-line:

gulp

Esto nos ejecutará la tarea default. Puesto que tiene la tarea _watch_ incluida, se ejecutará de forma indefinida hasta que se pare de forma manual.

Si por ejemplo queremos compilar los SCSS a CSS sólo una vez y no queremos ni tener la tarea de Watch activa ni la de BrowserSync, ejecutaríamos:

gulp sass

Y esto es todo, con este post espero haberos hecho una pequeña introducción a Gulp. Ahora podéis buscar más tareas, como por ejemplo minificar imágenes, validar y minificar js, e incluso modificar vuestro CSS para hacerlo más simple.

Os dejaré unos enlaces con distintos plugins que uso habitualmente o podéis entrar en http://gulpjs.com/plugins/ y haced vuestras búsquedas.

A disfrutar.

Links a plugins:

Publicado por Pedro García

Front-End Developer Certified Magento Front-End Developer & Magento Solution Specialist. @perichus