¡Automatiza tu entorno de desarrollo web!, con GruntJS + Browsersync

Con este tutorial tu día a día en el desarrollo web frontend, de diseñador web o incluso de programador web backend, cambiará.

En solo unos minutos te vas a montar un buen entorno de desarrollo web con un solo objetivo: AUTOMATIZAR TAREAS.

¿Qué vamos a automatizar? Tareas que haces continuamente de forma manual por ejemplo:

  1. Hacer que se recarge la página de tu navegador automáticamente cada vez que hagas cambios en un fichero, sin tener que actualizar tú el navegador de forma manual.
  2. Sincronizar pantallas de tablets, móviles y todos los dispositivos que quieras, es decir si haces scroll en una se hará en todas las pantallas, si haces click más de lo mismo, etc. Ideal para el desarrollo web responsivo, de un vistazo verás como queda todo sin tener que probar los dispositivos uno a uno.
  3. Escribir en SASS nuestros estilos y que al guardar los archivos .scss se compile automáticamente a un fichero CSS.
  4. Borrar el CSS que ya no usas en tu proyecto. Quizás debido a las prisas o por despiste te dejas rastros de basura de código en tu hoja de estilos o puede que uses frameworks frontend como Bootstrap o Foundation y te sobran clases. Con esta tarea puedes borrarte de un plumazo el código que no usas y reducir muchísimo el tamaño de tu archivo CSS.
  5. Minificar nuestros archivos css y JavaScript js para que ocupen menos peso en su puesta a producción. Por ejemplo: styles.min.css, scripts.min.js. Ya sabéis que Google valora que el tiempo de carga de una web sea rápido para el posicionamiento.
  6. Comprimir las imágenes de tu proyecto para reducir el tiempo de carga, con los formatos svg, jpg, png y gif.

Ya ves que la automatización significa reducir la inversión de tiempo y aumentar nuestra productividad, centrándonos en nuestros proyectos y dejando estas acciones en las manos de un gestor de tareas.

Automatizar tareas con Grunt.js y JavaScript

Grunt.js es un Task Runner (automatizador de tareas o ejecutor de tareas) en JavaScript que nos permite configurar tareas automáticas y así ganar productividad y reducir el tiempo de desarrollo y despliegue a producción de nuestras aplicaciones web.

Grunt trae un montón de plugins para automatizar tareas específicas (gruntplugins) y cada día van aumentando de número gracias a la gran comunidad que tiene detrás.

Automatizar tareas Grunt.js

El resumen: Grunt.js usa un fichero javascript que tienes que crearlo en la raíz de tu proyecto y nombrarlo como Gruntfile.js, en ese fichero escribimos las tareas que queremos automatizar y finalmente con un comando en consola ejecutamos Grunt que gestionará por nosotros esas tareas.

Grunt necesita un poco de Node.js para instalarse como módulo en nuestros proyectos y para instalar sus gruntplugins a través de NPM (Node Package Manager).

Primero instalamos globalmente Grunt cli (command line interface) y luego accedemos al proyecto que tenemos ya creado para instalarle grunt y sus plugins.

¿Nodejs, JavaScript, Gruntjs? ¡Soy Diseñador Web y me suena a chino!: No temas amigo, no es necesario para nada ser experto en Node o JavaScript para montarte un pedazo de entorno de desarrollo web. Te animo a seguir leyendo, ya verás que el resultado final merece la pena.

1) Instalación de Grunt CLI

Grunt.js y sus plugins se instalan y se gestionan por NPM (Node Package Manager). Por lo tanto debes tener instalado Node.js en tu equipo, esto ya lo contamos una entrada del blog, pero no me importa recordarlo en esta entrada también. Si acabas de aterrizar en este tutorial y andas un poco perdido sobre qué es Nodejs, puedes visitar esta entrada donde lo explico un poco;)

Instala primero Node.js si no lo tienes

Simplemente entra en la web de node y descarga Node. Ejecuta el instalador y dale a continuar sin más, ¡ya tendrás instalado Node y npm!, lo más fácil del mundo.

Instalación de Node

Instalación de Node

Hacemos una doble comprobación, ve a la consola y escribe: node -v y npm -v.

node -v y npm -v

node -v y npm -v

 

Si te aparece el temido “command not found” en una de las comprobaciones, asegúrate que node ha sido agregado a tu PATH. Esto nos permite usar node y los comandos npm en la línea de comandos de la terminal. Simplemente busca donde se instaló npm, copia la ruta, abre la ventana de variables de entorno y añade al path la ruta del npm. Reinicia tu ordenador y listo.

Si tienes otros problemas para instalar Node, consulta los siguientes enlaces:

Instalación de grunt-cli

Antes asegúrate que tienes actualizado NPM ejecutando este comando en la terminal npm update -g npm.

Ahora debemos instalar Grunt CLI (command line interface) de forma global en nuestro equipo, si usas Mac u otro sistema Unix quizás sea necesario añadir al principio de este comando la instrucción sudo (en el caso de que no tengas permisos):

Este comando dejará preparado el PATH de Grunt en las variables de tu sistema, de esta forma puedes usarlo y ejecutarlo en cualquier directorio de tu ordenador.

Pero ojo, con esto no hemos instalado Grunt, la función de Grunt CLI es que te permite tener multiples versiones de Grunt instaladas en tu máquina, ya que Grunt.js puedes instalarlo de forma individual para cada uno de tus proyectos o si lo prefieres de forma global en tu equipo.

Se recomienda como buena práctica instalar grunt de forma individual en cada proyecto / directorio localmente y no de forma global, para así no tener conflicto entre versiones llegado el caso. También depende de la forma en que estés acostumbrado a trabajar.

2) Preparar nuestro proyecto para usar Grunt.js

Debemos añadir a la raíz de nuestro proyecto dos ficheros: Package.json y el Gruntfile.js.

Añadimos el fichero Package.json

El Package.json es el archivo de configuración de tu proyecto (que usa npm para gestionar las dependencias), y contiene una lista con las herramientas que instalaremos (llamadas devDependencies) y otros datos de información opcionales como el nombre del proyecto, la versión, autor, etc.

Para crear un fichero Package.json básico abrimos la consola o terminal, nos situamos en la raíz del proyecto(en mi caso voy a usar el del tutorial de MaterializeCSS) y ejecutamos la siguiente instrucción:

Ahora la consola te va a bombardear a preguntas para crear el Package.json, no hace falta que leas mucho, solo pulsa enter o intro hasta llegar al final:

Automatizar tareas con Gruntjs

Para finalizar tienes que escribir yes y ya se creará el package.json en la carpeta de tu proyecto, en mi caso quedó así:

Si quieres puedes usar este package.json que he simplificado con la información básica necesaria:

Instalamos Grunt localmente

Vamos a instalar la última versión de Grunt.js (el módulo) en las carpetas de nuestro proyecto, para ello introduce el comando:

Recuerda usar sudo para Mac y sistemas unix.

Este comando no solo ha instalado el modulo grunt de forma local, si no que también ha añadido la sección devDependencies a tu package.json. Como dijimos antes, aquí se irán añadiendo las dependencias o herramientas que usemos en el proyecto, en este caso si abres el package.json verás que nuestra primera dependencia es Grunt.js y su versión actual:

También se ha creado la carpeta node_modules, donde se irán guardando los plugins que vayamos instalando.

Añadimos el fichero Gruntfile.js

Las tareas que vamos a automatizar las indicamos en el fichero Gruntfile.js, que es un simple documento javascript. En él se cargan los plugins y la configuración de estas tareas. Les damos instrucciones de dónde encontrar nuestros archivos y qué hacer con ellos, también definimos el orden en que se van a ejecutar.

Al igual que el package.json, debemos crear el Gruntfile.js en la raíz de nuestro proyecto. Esto lo hacemos de forma manual. Abre un nuevo documento y nómbralo como Gruntfile.js y copia este contenido inicial dentro de él:

Por ahora nos vale esto, más adelante añadiremos las tareas, que deben ir siempre dentro de la función de arriba.

Resumen

Estas son todas las configuraciones que necesitábamos, básicamente hemos hecho esto:

  1. Instalar Node.js
  2. Instalar grunt-cli globalmente, con el comando npm install -g grunt-cli
  3. Entrar en nuestro proyecto y crear el Package.json, con el comando npm init
  4. Instalar Grunt localmente en el proyecto con el comando, npm install grunt savedev
  5. Crear de forma manual el archivo Gruntfile.js en ese mismo directorio

¡Ahora vamos a ir añadiendo las tareas (grunt tasks)!, quizás te interesen todas las del tutorial o solo una parte.

Tareas de Grunt.js para montarte un entorno de desarrollo web muy PRO

En tu vida diaria de desarrollador web hay infinidad de tareas que puedes automatizar con Gruntjs, en esta entrada vamos a centrarnos en tareas que suele usar un programador web frontend o un diseñador web, no obstante hay tareas aplicables al frontend y al backend como la de guardar los ficheros y que visualices esos cambios en tu navegador sin tener que recargar.

Hay una task esencial que debes instalar: WATCH

Antes de nada instala la task watch, que es una de las tareas más importantes y útiles de Grunt. Lo que hace es “observar los cambios”, es decir, ejecuta ciertas tareas cuando hay cambios en los archivos que queremos “observar”. Por ejemplo en este código:

Imagina que tenemos instalado el gruntplugin sass para compilar SASS a CSS, dentro de la task watch le estamos diciendo que cada vez que detecte un cambio en los archivos .scss situados dentro de la carpeta “app/scss/”, se ejecute la tarea [‘sass’].

En este ejemplo lo que nos ahorra básicamente es estar escribiendo todo el rato en consola grunt sass para ejecutar la task sass cada vez que hacemos un cambio en el fichero .scss.

¿Has comprendido ya la enorme utilidad de la task watch?, vamos a usarla siempre con el resto de tareas.

Para instalar el grunt plugin watch nos vamos al directorio raíz de nuestro proyecto y escribimos:

Y verás que se ha actualizado el archivo package.json con la nueva dependencia.

Así es como quedaría la task watch añadida a nuestro Gruntfile.js. Por ahora la dejamos vacía:

Con grunt.loadNpmTasks(‘nombre-de-la-tarea’) cargamos la tarea en el archivo Gruntfile.js

 ¡Adelante con las tareas!

 

Browsersync gruntjs

Recargar automáticamente los cambios de tus ficheros en el navegador con BrowserSync

Cada vez que guardamos un fichero .css, .php, .html, etc, debemos ir al navegador y actualizar de forma manual con F5 o dándole al botón Cargar página de nuevo de Chrome. Vamos a automatizar esto con el gruntplugin BrowserSync.

Primero vamos a la raíz de nuestro proyecto e instalamos el grunt plugin BrowserSync:

Una vez instalado abrimos el Gruntfile.js y añadimos la tarea BrowserSync como tal, debemos indicarle dónde están nuestros archivos partiendo de la raíz de nuestro proyecto.

¿Sueles trabajar abriendo los ficheros .html, .php, etc, en tu navegador a pelo o tienes montado un servidor local (con apache y XAMPP por ejemplo) con tu hostname y todo eso?

Lo ideal es que tengas tus proyectos bien montados con un hostname http://tuproyecto.dev o tuproyecto.local, pero por si acaso no es así voy a darte las dos alternativas de BrowserSync.

Siguiendo mi ejemplo del proyecto tutorial-materialize, si trabajara con él abriéndolo de forma estática, mi Gruntfile.js con la task BrowserSync quedaría así:

Ahora bien, si tienes montado un buen servidor local PHP o algo parecido (en mi caso XAMPP) , con un hostname creado, necesitarás usar el modo proxy de Browser Sync. Donde indicas la url de tu sitio:

Te habrás fijado que al final he definido una tarea por defecto con el método registerTask, de esta forma ejecutamos tareas distintas en un solo comando, especifico que tareas voy a ejecutar al escribir en consola el comando ‘grunt‘ sin argumentos.

Dicho esto, vamos a la consola y ejecutamos el comando grunt, que hemos definido como tarea por defecto:

Desarrollo web Browser Sync

Por defecto se ejecuta en el puerto 3000

 

Se te abrirá una nueva pestaña en tu navegador con el localhost:3000 por defecto, mostrando tu web.

Ahora puedes cambiar cualquier fichero y guardarlo, ¡verás los cambios instantáneamente en tu navegador sin necesidad de recargar!

Truquito para desarrolladores backend: BrowserSync reconoce los cambios en cualquier fichero, no está limitado a inyectar CSS, yo mismo lo uso con Laravel 5. La configuración que tengo para acceder a todas las carpetas es esta:

 

Sincronizar navegadores browsersync

Sincronizar tu navegador con el móvil, tablet y todos los dispositivos que quieras

Esto en realidad ya lo hemos hecho al montarnos la tarea de Browser Sync, fíjate que al ejecutarla se nos muestra en consola una url Local y otra External, pues bien, ve a tu navegador móvil o tablet e introduce la url External.

En mi caso es http://192.168.1.129:3000

¡Pues usar tantos dispositivos como quieras y sincronizar navegadores!, verás que cuando haces scroll en uno se aplica a todos. También te simula los clicks y por supuesto, cada vez que cambies estilos o cualquier tipo de fichero se actualizarán todos los navegadores a la vez.

BrowserSync Workflow

Un buen entorno de desarrollador web con BrowserSync. Queda bastante pro, digno de la Batcueva.

 

*Soluciones a posibles problemas para acceder la URL External desde otros dispositivos:

Si al acceder a la URL External te aparece esto en tu navegador Chrome de Android: ERR_ADDRESS_UNREACHABLE. Puede deberse a dos cosas:

a) Tu Firewall está bloqueando el acceso a través de otros dispositivos, modifica la configuración de tu Firewall para dar acceso al puerto 3000.

b) Si a pesar de tener el Firewall desactivado o configurado para que permita la URL External, te sigue fallando, lo que debes hacer es abrir el puerto 3000 desde tu router. Para ello accede al login de tu router con un usuario y contraseña. Debes introducir una dirección en tu navegador (depende la compañía que tengas contratada). En mi caso es Jazztel y el acceso al router es por esta URL http://192.168.1.1/. En cuanto al login y contraseña casi siempre suelen ser:

  • admin/1234
  • admin/admin (esta me funcionó a mí)
  • 1234/1234
  • 1234/admin
  • root/12345

Una vez logueado en el panel de administración de tu router, haz click en Advanced Setup > NAT > Virtual Servers, y pulsa en el botón Add.  Rellena los datos de la imagen de abajo (cambia mi IP asignada por la tuya) y pulsa en Apply/Save:

Habilitamos el puerto 3000 para poder acceder a él desde fuera.

Habilitamos el puerto 3000 para poder acceder a él desde fuera.

Listo, ya tienes el puerto 3000 configurado, espero que ya puedas disfrutar de toda la potencia de BrowserSync para el desarrollo paginas de web.

 

Compilar Sass

Compilar automáticamente de  SASS a CSS al guardar los archivos .scss con Grunt Sass

Doy por hecho que cada vez escribes más Sass por sus claras ventajas en el diseño web modular, frente a escribir css. Si no es así puedes saltarte esta task, o bien si sientes curiosidad por Sass puedes echarle un vistazo a este post.

Vamos a automatizar la compilación de los ficheros .scss a .css, para ello instalamos la tarea gruntcontribsass con este comando en consola:

Ahora necesitamos decirle a Grunt dónde encontrar tus ficheros y dejar preparada la task sass. Así es como quedaría el fichero Grunt.js con la task Sass añadida:

La configuración de arriba está hecha asumiendo que tienes una estructura de directorios como esta:

Fíjate que debemos cargar el gruntplugin sass con loadNpmTasks junto a las otras tareas. A la tarea por defecto de abajo no tenemos por qué añadirlo ya que el gruntplugin watch está constantemente “vigilando” esos cambios que hagamos y éste ya lo tenemos añadido en la tarea por defecto.

Inicia otra vez la tarea por defecto con el comando grunt. Ahora cada vez que editemos nuestro fichero .scss se ejecutará nuestra tarea sass y se compilará al fichero .css en la ruta especificada, por supuesto todo esto de lo mantiene sincronizado en tus pantallas con la tarea Browser Sync anterior:

Aprender desarrollo web ágil con grunt

Ya tenemos dos tareas de Grunt: Sass y BrowserSync

 

Poco a poco irás viendo que aprender desarrollo web ágil es de lo más sencillo con Grunt, ¡genial!, vamos con la siguiente tarea.

 

Borrar css que no se usa

Borrar el CSS que no uses en tu proyecto con el grunt plugin UnCSS

Como desarrollador web te habrás dado cuenta que las prisas nos hacen dejar rastros de clases y otros selectores css en nuestro proyecto que no usamos. También puede darse el caso de que uses frameworks como Boostrap o Foundation, de los cuales los desarrolladores web suelen emplear menos del 10% de sus estilos.

Al final todo esto se traduce a archivos css pesados que podemos reducir considerablemente gracias a esta tarea: grunt uncss.

Como siempre, primero debemos instalar esta task, vamos desde la consola o terminal a la raíz de nuestro proyecto y escribimos:

El ejemplo sobre el Tutorial Materialize CSS que estamos usando nos viene genial, ya que materialize css es un framework y nos sobran muchísimos elementos de la hoja de estilos que no utilizamos.

Nuestro Gruntfile.js con esta task añadida quedaría así:

Fíjate que esta vez no vamos a usar esta task con la task por defecto. He preferido ponerla aparte y ejecutarla manualmente, creo que es algo que haríamos al finalizar el desarrollo y no durante éste.

Le pasamos una serie de parámetros como opción, la hoja de estilos que queremos limpiar y los estilos que queremos ignorar. Luego en files indicamos el nombre del fichero de salida y los archivos .html, .php, etc, que queramos escanear. Puedes ver todas las opciones en la versión de node de esta tarea, valen igualmente su versión en grunt.

Esta tarea también te agrupa todos los ficheros css en uno solo de salida, por eso en mi caso uso la opción ignoreSheets. Solo quería hacerlo con la hoja de estilos materialize.min.css.

Por supuesto también puedes scanear varios ficheros a la vez:

También puedes ignorar ciertos selectores y clases que no quieres cargarte por ahora o quizás las añadas al DOM posteriormente por la ejecución de una función javascript en determinadas interacciones:

 

Repito que si no le pasamos opciones de restricción, este grunt plugin te agrupa todos los css en uno por defecto. En la documentación tienes todo lo necesario.

Como no hemos añadido esto a la tarea grunt por defecto, para ejecutar esta task debemos ir al a consola y escribir:

Tutorial task grunt uncss

Fíjate como se reduce el peso del archivo con la task grunt uncss

Pues ya tenemos el fichero limpio, el único problema es que los archivos css que tuvieras minificados (.min.css) se te volverán a descomprimir, pero no te preocupes, ¡vamos a solucionar esto con la siguiente task!

 

Minificar CSS y Javascript

Minificar archivos CSS y JavaScript con grunt cssmin y grunt uglify respectivamente

Minificar archivos consiste en hacerlos menos pesados modificando elementos como espacios innecesarios, tabulaciones, comentarios, etc. Con JavaScript lo que se hace es cambiar el nombre de las variables por otros más breves para ahorrar caracteres. Cuanto más bytes de código nos ahorremos, más mejorará la velocidad de carga de nuestra página y nuestra nota en el Google Page Speed.

Minificar css con cssmin

Usaremos el grunt plugin cssmin. Para instalarlo vamos a la consola y nos situamos en la raíz de nuestro proyecto, escribimos:

Lo que vamos hacer es combinar nuestros css en un solo archivo minificado (.min.css). Lo ideal es que trabajes con tus css sin minificar en desarrollo y luego en el despliegue a producción subas todos combinados en un solo archivo .min.css, en este caso lo he llamado allcss.min.css.

Abrimos el Gruntfile.js y primero añadimos esta task cssmin dentro la task watch, ya que nos interesa que cada vez que hagamos un cambio en los archivos css watch lo perciba y llame a la task cssmin para que nos genere inmediatamente el nuestro .css minificado y combinado:

Luego añadimos la task cssmin, aquí tienes su configuración. Le indicamos un fichero de salida y los archivos css que queremos combinar y minificar:

Por último ejecuta como siempre la tarea por defecto con el comando grunt y verás que al guardar en cada .css se genera inmediatamente una combinación de todos tus css en un solo fichero ya minificado:

Minificar css con grunt cssmin

Minificar css con grunt cssmin

 

Minificar javascript con uglify

Uglify es una task de grunt muy buena para la minificación de javascript. También tiene muchas opciones en la documentación, como combinar tus archivos javascript en un solo archivo, aunque esto debe hacerse con cuidado y lo recomendable es que cada archivo que tengas lo envuelvas en IIFE (Immediately Invoked Function).

Nosotros simplemente vamos a minificar un archivo o archivos Javascript concretos.

Primero instalamos uglify con este comando:

Luego lo añadimos dentro de la task watch para que detecte cambios en nuestros archivos javascript e ignoramos los ya minificados:

Lo siguiente es añadir la task uglify  y su configuración. Indicamos la ruta de donde grunt cogerá los ficheros javascript y la ruta donde los soltará ya con el javascript minificado:

Por último usa el comando grunt en tu terminal o consola para iniciar las tareas que tenemos definidas, verás que al guardar tus archivos .js se genera el archivo javascript minificado .min.js:

Minificar javascript con uglify

Minificar javascript con uglify

Gruntfile con nuestras dos tareas de minificación añadidas:

 

Optimizar imagenes gruntjs

Comprimir imagenes jpg, png, svg y gif con grunt imagemin

Una de las tareas más pesadas es la de comprimir y optimizar las imágenes del proyecto para mejorar los tiempos de carga. Grunt nos ofrece la task imagemin para acelerar este proceso.

Para instalarla nos vamos a la consola y situados en la raíz de nuestro proyecto escribimos:

Abre el Gruntfile.js y carga imagemin junto al resto de grunt plugins:

Añade la task imagemin configurada al resto de tareas:

Y añade imagemin también dentro de la tarea watch para que cada vez que metas una nueva imagen en tu directorio /img se compriman éstas automáticamente:

Bien, si ejecutas grunt en consola verás que cada vez que guardes una imagen en el directorio que has indicado se reducirá de peso automáticamente:

Comprimir imagenes con grunt imagemin

Comprimir imagenes con grunt imagemin

¿Pero qué pasa si tenemos muchas imágenes que optimizar?, se comprimirán todas una y otra vez, haciendo que el proceso sea lento y tedioso.

Para evitar que esta task vuelva a optimizar las imágenes ya comprimidas, podemos usar el grunt plugin newer, que se dedica a detectar qué imágenes nuevas se han añadido recientemente a tu carpeta para así trabajar solo con ellas.

Vamos allá:

Cargamos la task newer en el Gruntfile.js:

Y no hace falta configurarlo, lo metemos dentro del watch que tenemos nombrado para imagemin:

Se debe anteponer newer a la task imagemin.

Archivo Gruntfile.js final, con todas las tareas añadidas

 

Package.json final, con todas las dependencias necesarias

Instalación de todas las task en cualquier proyecto de forma rápida

Si quieres ir directo al grano ve a tu proyecto haz el npm init y crea el package.json, a ese package.json debes añadirle el siguiente fragmento con las dependencias:

Luego copia el Gruntfile.js completo que tienes más arriba y modifica la ruta de las carpetas, etc, a tu gusto.

Por último haz un npm install en consola y node te instalará grunt y todas las dependencias que hay en tu package.json.

¡Se acabó!

Conclusiones finales

Lo más seguro es que no tengas la necesidad de usar las 6 automatizaciones de este tutorial, a la gente le suele encantar BrowserSync, ya que es la más vistosa y la que más alucinado te deja.

Pero en el desarrollo de páginas web, sobre todo a la hora de optimizar nuestras webs para el Google Page Speed, nos vienen genial también las tareas de minificar css, javascript y comprimir imagenes.

Como desarrollador web he intentado buscar un equilibrio con Grunt y estas tareas, esta selección de tareas grunt es meramente personal.

Al fin de cuentas, es tu entorno de desarrollo web, tú decides como montártelo ;).

No olvides comentar si tienes algún fallo en la instalación o alguna duda, ¡comparte si te ha sido útil!

11 Comentarios

  1. salotroll 14 agosto, 2015 Responder
    • amldesign amldesign 15 agosto, 2015 Responder
  2. Gerardo Argueta 20 octubre, 2015 Responder
    • amldesign amldesign 20 octubre, 2015 Responder
  3. Juliana 2 enero, 2016 Responder
  4. moises 14 marzo, 2016 Responder
  5. Duvan 3 mayo, 2016 Responder
  6. Hécto Pulido 6 mayo, 2016 Responder
  7. Jorge Mario Romero Arroyo 19 mayo, 2016 Responder
  8. Paco Vargas 25 junio, 2016 Responder

Añadir un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *