FRONT-END:HERRAMIENTAS Y ENTORNO UX
Entorno de automatización para el trabajo en proyectos orientados a AngularJS
Versión: 1.6 / Fecha: 21/12/2016
CONTROL DE VERSIONES
Versión Fecha de Actualización Comentarios
0.1 09/11/2016 Creación del documento inicial
0.2 14/11/2016 Documentación de la sesión 1 del curso
0.3 15/11/2016 Documentación de la sesión 2 del curso
0.4 16/11/2016 Documentación de la sesión 3 del curso
0.5 17/11/2016 Documentación de la sesión 4 del curso
0.6 18/11/2016 Documentación de la sesión 5 del curso
0.7 21/11/2016 Documentación de la sesión 6 del curso
0.8 22/11/2016 Documentación de la sesión 7 del curso
0.9 23/11/2016 Documentación de la sesión 8 del curso
1.0 24/11/2016 Documentación de la sesión 9 del curso
1.1 25/11/2016 Completado de la documentación final del curso
1.2 15/12/2016 Añadida la sección de configuración del editor y correcciones varias
1.3 16/12/2016 Añadido el punto para la corrección de errores en procesado SASS
1.4 16/12/2016 Añadida configuración de puertos en BrowserSync
1.5 19/12/2016 Añadida sección para generar la guía de estilos
1.6 21/12/2016 Añadida referencia de consulta para la sintaxis de Markdown
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 2 de 47
I N D I C E
1. Composición del entorno............................................................................................................................... 51.1. Ventajas del entorno de desarrollo.......................................................................................61.2. ¿Qué es NodeJS?...................................................................................................................61.3. ¿Qué es NPM?.......................................................................................................................61.4. ¿Qué es Bower?....................................................................................................................71.5. ¿Qué es Gulp?.......................................................................................................................71.6. ¿Qué es PUG?........................................................................................................................81.7. ¿Qué es SASS?......................................................................................................................81.8. Editores y requisitos mínimos...............................................................................................8
2. Creación de entorno base del proyecto......................................................................................................102.1. Instalación y configuración de Visual Studio Code..............................................................102.2. Instalación de Node, Git y configuración de proxy..............................................................122.3. Creación de configuración NodeJS.......................................................................................142.4. Creación de configuración Bower........................................................................................152.5. Instalación de paquete gulp y plugins para gulpfile básico.................................................162.6. Creación de la estructura del proyecto...............................................................................17
3. Procesado de HTML..................................................................................................................................... 183.1. Instalación de PUG..............................................................................................................183.2. Buenas prácticas en HTML..................................................................................................183.3. Creación de tarea de procesado PUG en Gulpfile.js............................................................19
4. Procesado de CSS........................................................................................................................................ 204.1. Instalación de SASS.............................................................................................................204.2. Buenas prácticas en SASS...................................................................................................204.3. Creación de tarea de procesado SASS en Gulpfile.js...........................................................20
5. Procesado de JS........................................................................................................................................... 225.1. Buenas prácticas en JS........................................................................................................225.2. Creación de tarea de procesado JS......................................................................................23
6. Procesando librerías de terceros................................................................................................................246.1. Instalación de USEREF........................................................................................................246.2. Creación de tarea de procesado USEREF............................................................................246.3. Instalación de librerías jquery y bootstrap mediante Bower................................................246.4. Uso de build useref dentro del código HTML.......................................................................25
7. Automatización de HTML, CSS y JS...........................................................................................................267.1. Instalación de Gulp Watch...................................................................................................267.2. Creación de tarea de escucha para el procesado automático de PUG, SASS y JS................267.3. Corrección de errores en procesado de SASS.....................................................................27
8. Servidor en vivo............................................................................................................................................ 28
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 3 de 47
8.1. Instalación de BrowserSync................................................................................................288.2. Creación de tarea para servir estáticos...............................................................................288.3. Testing de eventos multidispositivo mediante browsersync...............................................308.4. Configuración de consola BrowserSync...............................................................................30
9. Preparación del entorno para distribución y metodología.......................................................................349.1. Minificado de librerías de terceros......................................................................................349.2. Creación de tareas de metodología.....................................................................................34
9.2.1. Metodología en CSS mediante CSSLint..........................................................................................................35
9.2.2. Compatibilidad de CSS3 con Autoprefixer.......................................................................................................36
9.2.3. Metodología en JS mediante JSHint................................................................................................................36
9.3. Creación de tareas adicionales...........................................................................................389.3.1. Tareas de copiado de ficheros.........................................................................................................................38
9.3.2. Tareas de limpiado de ficheros.........................................................................................................................39
9.3.3. Watchers para copiado de ficheros..................................................................................................................40
9.4. Completado de tareas de distribución.................................................................................419.4.1. Completado de la tarea SASS..........................................................................................................................41
9.4.2. Completado de la tarea COPY.........................................................................................................................42
9.4.3. Creación de tarea DIST:TEST..........................................................................................................................42
9.4.4. Creación de tarea DIST:ZIP.............................................................................................................................43
10.Creación de guía de estilos......................................................................................................................... 4410.1. Instalación del plugin y tareas gulp.............................................................................4410.2. Creación de estructura y estilos mediante KSS...........................................................46
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 4 de 47
1. Composición del entornoEl objetivo de la creación del entorno para proyectos UX, es disponer de una serie de herramientas de
automatización, preprocesado y minificación para poder comenzar cualquier proyecto de UX de forma fácil
siguiendo una serie de metodologías ágiles, que facilitarán el desarrollo de proyectos y proveerán de una
base de conocimientos para trabajar con proyectos modernos como los basados en AngularJS.
La base sobre la que se ha partido para la creación del entorno:
NODE como base para todo el proyecto.
GULP como sistema de automatización de tareas.
BROWSERSYNC como servidor de aplicaciones 'en vivo'.
PUG como lenguaje de plantillas para generar el código HTML.
SASS como lenguaje para el preprocesado de CSS.
SASS + AUTOPREFIXER para dar soporte de vendor prefixes a los navegadores que elijamos.
SASS + CSSLINT para asegurar que se utiliza CSS con buenas prácticas.
JS + JSHINT para asegurar las buenas prácticas en código JavaScript.
USEREF para unificar y minimizar CSS/JS de terceros.
MINIFICADORES tanto para CSS como JS, para optimizar el rendimiento y peso del proyecto.
IMAGEMIN para optimizar el tamaño de las imágenes
SC5-STYLEGUIDE para generar la guía de estilos
PRESENTACIÓN
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 5 de 47
1.1. Ventajas del entorno de desarrollo
La principal ventaja de disponer de un entorno de desarrollo basado en gulp es la total y completa
automatización de las tareas, para que una vez hayamos definido las tareas que vamos a necesitar,
sólo tengamos que preocuparnos de desarrollar nuestra aplicación. De modo que con una serie de
tareas analizaremos la calidad del código, optimizaremos la entrega y las dependencias del
proyecto de una forma muy sencilla y transparente para del desarrollador.
También facilita la tarea de desarrollo colaborativo, ya que sólo tenemos que subir nuestra carpeta
src y los ficheros de configuración a un repositorio de control de versiones. Así cualquiera que
descargue el proyecto solo tiene que ejecutar los comandos de instalación npm install && bower install y se instalarán todas las dependencias de plugins node y bower que hemos configurado
para nuestro proyecto.
1.2. ¿Qué es NodeJS?
Node.js es un entorno Javascript del lado del servidor, basado en eventos. Node ejecuta javascript
utilizando el motor V8, desarrollado por Google para uso de su navegador Chrome. Aprovechando
el motor V8 permite a Node proporciona un entorno de ejecución del lado del servidor que compila y
ejecuta javascript a velocidades increíbles. El aumento de velocidad es importante debido a que V8
compila Javascript en código de máquina nativo, en lugar de interpretarlo o ejecutarlo como
bytecode. Node es de código abierto, y se ejecuta en Mac OS X, Windows y Linux.
JavaScript es un sólo un lenguaje de programación del lado del cliente que se ejecuta en el
navegador, ¿verdad?. Ahora ya no. Node.js es una forma de ejecutar JavaScript en el servidor,
entre otros tantos usos que le podemos dar.
1.3. ¿Qué es NPM?
NPM o Node Package Manager es el gestor de paquetes de node, con el instalamos cualquier
plugin desarrollado bajo la arquitectura Node que requiera nuestro proyecto de forma sencilla.
Además, su principal ventaja es que incorpora un gestor de dependencias, pues cada vez que
instalamos un plugin podemos indicarle que lo guarde como dependencia de nuestro proyecto.
Por defecto cuando instalamos un paquete y lo guardamos como dependencia, npm se encarga de
instalar el paquete de la misma rama, es decir si instalamos gulp 3.9.1 y lo guardamos como
dependencia, siempre que no cambie de rama en la información del paquete, instalará la última
versión de la rama, Ej.: gulp 3.9.2, gulp 3.9.3, pero no gulp 3.10.0.
Para instalar las dependencias especificadas en el proyecto (package.json):npm install
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 6 de 47
Para instalar un paquete de forma global (accesible desde cualquier directorio)npm install -g nombrepaquete
Para instalar un paquete sólo en nuestro proyecto:npm install nombrepaquete
Para instalar un paquete en nuestro proyecto y guardarlo como dependencia:npm install nombrepaquete --save
npm install nombrepaquete --save-dev
Para instalar un paquete y guardar como dependencia la versión exacta:npm install nombrepaquete --save --save-exact
Para instalar una version concreta de un paquete:npm install nombrepaquete@version
Por último, si queremos actualizar el paquete y su dependencia en nuestro package.json, sólo
tenemos que realizar de nuevo npm install --save ó --save-dev y guardará la dependencia en la
última versión de su rama.
Repositorio de paquetes de Node/NPM: https://www.npmjs.com/
1.4. ¿Qué es Bower?
Bower es un plugin de Node para gestión de dependencias, para librerías y frameworks JS/CSS
tales como jQuery, AngularJS, Bootstrap, etc… Al igual que NPM, cuando instalamos una librería de
bower, podemos especificar que la guarde como dependencia del proyecto a la vez que se instala.
Repositorio de paquetes de Bower: https://bower.io/search/
1.5. ¿Qué es Gulp?
Gulp es una herramienta ‘task runner’, sirve para automatizar tareas. Mediante Gulp se define cómo
deben ejecutarse esas tareas.
Estas herramientas construyen estructuras y tareas comunes para todos los desarrolladores.
El uso típico incluiría:
Compilación de CSS y JavaScript preprocesado.
Concatenación.
Minificación.
Lanzar un servidor para la recarga automática en el browser.
Creación de una build para despliegue.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 7 de 47
1.6. ¿Qué es PUG?
Es conocido como un Template Engine, si pudieras compararlo con algo, sería como un pre-
procesador HTML muy parecido a los que usamos para facilitarnos la vida con CSS (SASS, Less,
Stylus…). Está implementado en JavaScript para trabajar de la mano con NodeJS ofreciendo a los
desarrolladores una forma dinámica, eficaz y expresiva para generar nuestro código en corto tiempo
y con menos líneas de código.
Ventajas:
No hay etiquetas de cierre
Uso de indentación (sangría) para la jerarquía
Apoyo de JavaScript y otras herramientas
Sistema de layouts, includes y extensiones de templates
Posibilidad de generación dinámica de pug mediante JS así como carga asíncrona
mediante AMD.
Posibilidad de escoger el formato del código generado (minificado o completo)
Generación de HTML perfectamente indentado y legible.
1.7. ¿Qué es SASS?
Sass es un lenguaje de preprocesado de CSS. La principal ventaja de SASS es la posibilidad de
convertir los CSS en algo dinámico. Permite trabajar mucho más rápido en la creación de código
con la posibilidad de crear funciones que realicen ciertas operaciones matemáticas y reutilizar
código gracias a los mixins, extensiones de clases y variables que nos permiten guardar valores.
Sus principales ventajas:
Permite convertir el código CSS en modular, facilitando enormemente el mantenimiento del
proyecto.
Permite crear código anidado (nested), ayudando así a diferenciar unos elementos de otros
gracias a su nivel de anidamiento (herencia).
Uso de variables y funciones avanzadas (mixins).
1.8. Editores y requisitos mínimos.
A la hora de editar cualquier archivo de configuración o fuente de nuestro proyecto podemos utilizar
cualquier editor que soporte SASS, PUG y JavaScript. En realidad podemos utilizar cualquier editor,
pero se recomienda que disponga de la correcta identificación y coloreado de elementos para
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 8 de 47
dichos lenguajes, pues de lo contrario perdemos una de las ventajas principales del uso de dichos
lenguajes: La facilidad de lectura del código.
Principalmente se recomienda la utilización de Visual Studio Code. Optamos por el, debido
principalmente a que de serie trae el soporte de lenguajes que necesitamos, la licencia de uso es
gratuita, podemos ampliar sus funcionalides mediante la instalación de plugins a través de su propio
Marketplace de Plugins y dispone de una consola de comandos integrada en el propio editor, lo que
nos facilitará las tareas que iremos realizando mediante la ejecución de comandos en dicha consola.
Otros editores a tener en cuenta son Atom y Brackets (Gratuitos y multiplataforma) y Sublime Text
(Multiplataforma, de pago).
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 9 de 47
2. Creación de entorno base del proyecto
2.1. Instalación y configuración de Visual Studio Code
La instalación de Visual Studio Code, es sencilla, sólo hay que ejecutar el instalador y establecer si
queremos asociar los archivos al editor. Con la configuración por defecto se instalará correctamente.
Una vez instalado, se recomienda ejecutarlo y realizar la configuración mostrada a continuación:
Archivo > Preferencias > Tema de Color > Monokai
Archivo > Preferencias > Tema de Iconos > Seti (Visual Studio Code)
En cuanto a los temas de código e iconos, es de libre elección del usuario con los que se sienta más
cómodo. Pero al menos se recomienda utilizar un esquema de colores que identifique
correctamente todos los elementos, objetos, variables, parámetros, etc… de nuestro código. El tema
de los iconos, nos ayuda visualmente a distinguir más claramente los archivos y directorios con los
que trabajamos.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 10 de 47
Para evitar problemas con la mezcla de espaciados y tabulaciones, configuraremos unos
parámetros en nuestras preferencias personales:
Archivo > Preferencias > Configuración de usuario
Básicamente configuraremos el editor para que utilice tabulaciones en lugar de espacios y además
nos muestre de forma visual los espacios y tabulaciones:
{
"editor.renderWhitespace": "boundary",
"editor.insertSpaces": false,
"editor.detectIndentation": false
}
Una vez activadas estas opciones, en nuestro código aparecerá una para identificar tabulaciones
y un punto cada vez que introduzcamos un espacio:
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 11 de 47
2.2. Instalación de Node, Git y configuración de proxy
También necesitamos instalar NodeJS: https://nodejs.org/es/ y Git para Windows: https://git-for-
windows.github.io/.
Al instalar tanto NodeJS como Git, nos aseguraremos de seleccionar la instalación de ambos en el
PATH del sistema, para poder acceder a su línea de comandos desde cualquier proyecto.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 12 de 47
Una vez hayamos finalizado la instalación de visual studio code, nodejs y git para Windows,
procederemos a la configuración para poder trabajar con NPM (Gestor de paquetes de Node) y Git a
través del proxy de indra.
Configuración del proxy para NPM:
npm config set proxy http://USERNAME:[email protected]:8080
Si tenemos un carácter de la siguiente tabla en nuestra contraseña de usuario, debemos escaparlo
con el código hexadecimal correspondiente de la siguiente tabla (Sólo para NPM):
Hexadecimal Carácter especial
%40 @
%3A :
%21 !
%23 #
%24 $
Configuración del proxy para GIT:
git config --global http.proxy http://USERNAME:[email protected]:8080
git config --global https.proxy http://USERNAME:[email protected]:8080
Cada una de estas configuraciones no va a generar un archivo de configuración en nuestra carpeta
de usuario:
C:\Users\nombredeusuario\.npmrc en el caso de la configuración de NPM
C:\Users\nombredeusuario\.gitconfig en el caso de la configuración de GIT
Podemos acceder a dichos archivos más adelante para cambiar las credenciales o para verificar
que está correctamente configurado si experimentamos algún problema de conexión con los
repositorios.
El último paso para poder comenzar con nuestro proyecto, es la instalación de dos plugins de node
de forma GLOBAL para poder invocarlos desde cualquier proyecto (Gulp y Bower). Los plugins se
instalan de forma global con el parámetro –g en la instalación:
npm install -g gulp
npm install -g bower
Con la instalación de los programas aquí mencionados, la configuración de proxy realizada y la
instalación de estos dos plugins procederemos a la creación de nuestro proyecto inicial.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 13 de 47
2.3. Creación de configuración NodeJS
Para poder instalar los plugins necesarios para nuestro proyecto, debemos crear en primera
instancia una configuración de proyecto NodeJS. En esta configuración se almacenará la
información del proyecto, así como los plugins que instalemos y marquemos como dependencias
durante la instalación.
Para la creación de un nuevo proyecto ejecutamos el comando npm init sobre el directorio raíz de
nuestro proyecto, a través de una consola de comando, acto seguido nos aparecerán una serie de
preguntas acerca de nuestro proyecto, por norma general sólo especificaremos el nombre y la
descripción del mismo en el caso de que queramos cambiarlo.
Esta configuración se realizará la primera vez y nos genera un archivo de configuración
(package.json) ubicado en la raíz del proyecto, cuyo contenido es:
{
"name": "ejercicio",
"version": "1.0.0",
"description": "curso de ux",
"main": "index.js",
"scripts": {
"test": "gulp"
},
"author": "",
"license": "ISC",
"devDependencies": {
"del": "^2.2.2",
"gulp": "^3.9.1",
"gulp-pug": "^3.1.0"
}
}
En caso de que queramos añadir alguna información del proyecto o cambiar alguna dependencia lo
haremos editando el archivo package.json correspondiente a nuestro proyecto.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 14 de 47
2.4. Creación de configuración Bower
Del mismo modo que necesitamos un archivo de configuración para guardar la información y
dependencias de nuestro proyecto node, también necesitamos un archivo de configuración Bower
para guardar las dependencias de librerías que necesite nuestro proyecto. Para crear la
configuración ejecutamos el comando bower init. En este caso, obtiene la configuración del archivo
package.json de node y además nos realiza una serie de preguntas adicionales, la más importante
es decirle que NO queremos importar la librerías existentes como dependencias y que SI queremos
que nos añada a la configuración la lista de archivos comúnmente ignorados. En el caso de bower,
nos genera un archivo bower.json, con el siguiente contenido:
{
"name": "ejercicio",
"description": "curso de ux",
"main": "index.js",
"license": "ISC",
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
Con la creación de estos dos archivos de configuración (Node y Bower) ya podremos comenzar a
formar nuestro flujo de automatización.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 15 de 47
2.5. Instalación de paquete gulp y plugins para gulpfile básico
En puntos anteriores vimos cómo hemos instalado plugins de node a nivel global, y uno de ellos era
gulp, éste es necesario instalarlo a nivel global como a nivel de proyecto. En las siguientes
operaciones de instalación de paquetes a nivel de proyecto, siempre marcaremos dicho paquete
como dependencia del proyecto, para ello añadimos al final del comando el parámetro --save-dev
Para crear nuestro archivo gulpfile donde iremos configurando el flujo de automatización
necesitamos instalar el paquete gulp, con el comando: npm install gulp --save-dev
Una vez instalado el paquete crearemos el archivo gulpfile.js en la raíz de nuestro proyecto y lo
inicializaremos con la inicialización de variables y tareas básicas:
var gulp = require('gulp');
gulp.task('default', function(){
console.log('tarea por defecto');
});
Desde este mismo momento ya tenemos la configuración mínima que nos permitirá lanzar el
comando gulp con un resultado, en este caso un texto en consola con el valor tarea por defecto.
Se recomienda configurar el archivo package.json para que el comando test ejecute nuestra tarea
gulp por defecto, así a la hora de testear la correcta instalación de paquetes tendremos esa tarea
como prueba de que todo se ha instalado correctamente:
"scripts": {
"test": "gulp"
},
Para el resto de plugins node que vayamos a utilizar con nuestro gulpfile, hay que declarar la
variable correspondiente al inicio de nuestro fichero gulpfile:
var gulp = require('gulp'),
pug = require('gulp-pug'),
del = require('del'),
sass = require('gulp-sass'),
[...],
useref = require('gulp-useref');
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 16 de 47
2.6. Creación de la estructura del proyecto
Por norma general, la estructura de cada proyecto depende mucho de la naturaleza del desarrollo y
de los propios desarrolladores, aun así aconsejamos seguir una estructura de proyecto mínima
como la siguiente (La más común compartida por diversos proyectos):
src/
├─── features/ Secciones o páginas que componen nuestra aplicación
│ └─── sectionName/
│ ├─── sectionName.js Todo el JS, PUG y SASS en la misma carpeta
│ ├─── sectionName.pug siempre que sea de la misma feature.
│ └─── sectionName.scss
├─── components/ Componentes propios comunes o individuales
│ └─── componentName/
│ ├─── componentName.js Todo el JS, PUG y SASS en la misma carpeta
│ ├─── componentName.pug siempre que sea del mismo componente.
│ └─── componentName.scss
├─── services/ Toda la lógica relacionada con los servicios y conexiones
│ ├─── data.service.js
│ └─── logger.service.js
├─── app.main.js JavaScript principal de nuestra aplicación
├─── assets/
│ ├─── img/ Imágenes
│ ├─── css/ CSS Propio y de terceros (vendors)
│ ├─── js/ Javascript propio independiente de AngularJS
│ ├─── libs/ Librerías de terceros (vendors)
│ └─── fonts/ Tipografías para embeder mediante CSS
└─── index.pug Página principal de nuestra aplicación
Cuando incluyamos imágenes, tipografías, css y librerías de terceros, siempre se incluirán en
minúsculas y utilizando guiones o puntos para separar los nombres:
jquery.nombreplugin.min.js
jquery.nombreplugin.min.css
Si el plugin lo utilizamos a través de Bower, no modificaremos ningún archivo.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 17 de 47
# Estructura no modificable # Estructura generada por el usuario
3. Procesado de HTML
3.1. Instalación de PUG
Para la tarea de procesado PUG, necesitamos instalar el plugin gulp-pug, instalándolo como
dependencia del proyecto:
npm install gulp-pug --save-dev
3.2. Buenas prácticas en HTML
Para el desarrollo de los proyectos, se ha de utilizar HTML5, dado que queremos hacer un
desarrollo extensible, dinámico y lo más compatible posible con nuevas tecnologías. Se recomienda
seguir una serie de buenas prácticas para un desarrollo de calidad y mantenible:
Usa tabulador, y en el caso de que uses espaciado, 4 espacios.
Utilizar lo más preciso posible las etiquetas de HTML5 en lugar de utilizar los div habituales. En
HTML5 disponemos de etiquetas para enmarcar distintas zonas o elementos de nuestro
código, como <header> <footer> <nav> <aside> <section> <caption> etc., El uso de estas
etiquetas nos aseguran un marcado correcto, semántico y accesible.
Hay que asegurarse de usar correctamente y siguiendo una jerarquía lógica, las etiquetas de
Heading (H1, H2, H3, etc.). No podemos utilizar una etiqueta H1 y saltar a una etiqueta H3 si
no disponemos de una etiqueta H2 superior.
Etiquetado correcto de los elementos, por ejemplo si estamos presentando una lista de datos
simples, una serie de imágenes relevantes debemos utilizar una lista desordenada (UL > LI). Si
estamos mostrando datos complejos y asociados en serie debemos utilizar una tabla, etc.
Evitar el exceso de presentación bajo CSS. Ya que intentamos crear un marcado semántico y
accesible, deberemos en la medida de lo posible, utilizar imágenes (bitmap o vectoriales),
iconos tipográficos, etc., dentro del propio HTML, evitando la inclusión de dichos elementos en
CSS. Ya que por accesibilidad en el punto de control de contraste, estos elementos no son
tratados por los navegadores.
Definir correctamente la identificación de los elementos. Es muy importante identificar
correctamente los enlaces e imágenes utilizando las etiquetas ALT y TITLE, para una correcta
accesibilidad e identificación de las mismas.
No abusar del sobre etiquetado. Para la presentación de elementos, en muchas ocasiones
utilizamos muchos elementos HTML dentro de otros para hacer una presentación que se ajuste
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 18 de 47
a nuestras necesidades. Actualmente y gracias a las técnicas CSS podemos eliminar gran
parte de esos elementos HTML innecesarios utilizando pseudoelementos CSS, selectores
avanzados, etc. Siempre que podamos evitaremos el uso excesivo de elementos si no
entramos en conflicto con una buena semántica y accesibilidad.
En general si dudas a la hora de hacer un marcado HTML concreto, quizá es porque ese
marcado no corresponde con lo que debes utilizar, analízalo e investiga si lo que vas a hacer
es la forma correcta de hacerlo.
3.3. Creación de tarea de procesado PUG en Gulpfile.js
Creamos en nuestro gulpfile una tarea llamada pug para compilar todo el html del proyecto:
gulp.task('pug', function(){
return gulp.src('src/**/!(_)*.pug')
.pipe(pug({pretty: true}))
.pipe(gulp.dest('app'));
});
Por defecto, utilizaremos la api estándar de gulp y la única opción que cambiaremos en la función
.src(), donde indicaremos con una negación y el carácter a omitir entre paréntesis !(_) en la
expresión a buscar en el source. Esta expresión indica que todo lo que empiece por _ en el nombre
del archivo, ej: _parcial.pug no sea procesado por la tarea, ya que los usaremos para hacer
includes y extensiones de layout internamente al procesar los archivos principales.
Como parámetro opcional podemos definir que nos genere el html completo y correctamente
indentado, indicando el parámetro pretty:true en las opciones de pug. Si quitamos esta opción nos
generará el html minificado en una sola línea.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 19 de 47
4. Procesado de CSS
4.1. Instalación de SASS
Para la tarea de procesado SASS, necesitamos instalar el plugin gulp-sass, instalándolo como
dependencia del proyecto:
npm install gulp-sass --save-dev
4.2. Buenas prácticas en SASS
Debido a que vamos a utilizar CSSLint siempre que compilemos nuestro SASS no vamos a entrar
en las buenas prácticas de CSS porque el propio CSSLint nos avisará de los errores que podamos
cometer programando el CSS, por tanto vamos a centrarnos en las buenas prácticas a tener en
cuenta a la hora de trabajar con SASS.
Usa tabulador, y en el caso de que uses espaciado, 4 espacios.
Utiliza la estructura predefinida de parciales, estos son los archivos que van a formar nuestro
CSS. En nuestro proyecto se distinguen COMMONS o Globales y PARTIALS o Parciales. En la
carpeta commons se separa por tipos de elementos (Formularios, Tablas, Botones, Layout,
etc.), es una estructuración que hay que respetar. En la carpeta partials, se incluyen aquellos
estilos que requieren ser escritos a parte para una vista concreta, por ello crearemos un archivo
partial por cada vista en la que tengamos que añadir estilos independientes.
Cuidado con el anidamiento excesivo. Como vamos a partir de un proyecto de cero, no hay
ningún motivo para aplicar un anidamiento excesivo, salvo para el caso de sobre escritura de
estilos de terceros (bootstrap, librerías externas, etc.). Por norma general es mejor utilizar una
clase global para una vista concreta y utilizar un máximo de 3 niveles de anidamiento, en la
medida de lo posible, para optimizar el procesado y carga del CSS resultante.
Usa los comentarios correctamente. Los comentarios estándar de CSS /* como este */ se
compilan junto al CSS, por lo que para evitar que sea compilado, se recomienda utilizar los
comentarios de tipo Sass, precedidos de dos barras // Como este.
4.3. Creación de tarea de procesado SASS en Gulpfile.js
Creamos en nuestro gulpfile una tarea llamada sass para compilar todo el css del proyecto:
gulp.task('sass', function(){
return gulp.src('src/**/!(_)*.scss')
.pipe(sass().on('error', sass.logError))
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 20 de 47
.pipe(gulp.dest('app'));
});
Al igual que con la tarea de pug, usaremos la api estándar de gulp y añadiremos el comodín de
negación !(_) en la declaración de .src() para que no nos compile ninguno de los archivos que
vamos a utilizar como parciales.
En cuanto a configuración, el plugin gulp-sass permite añadir escuchadores de eventos para realizar
distintas acciones, por defecto recomiendan añadir el escuchador cuando hay un error y ejecutar un
logError, en nuestro caso: on(‘error’, sass.logError) para que nos muestre en consola los errores
que encuentre al procesar SASS y no detenga el flujo de la tarea.
Entre los parámetros que podemos configurar, está el formato de salida del CSS generado, de
momento no vamos a configurarlo, pero más adelante elegiremos formato comprimido o expandido
dependiendo de la tarea que ejecutemos.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 21 de 47
5. Procesado de JS
5.1. Buenas prácticas en JS
Hemos marcado unas pautas de desarrollo con respecto al JavaScript que vamos a utilizar, que
dado que trabajaremos con AngularJS será bastante. No se trata de limitar ni imponer una forma de
trabajar sino de definir una metodología, que cumpla unos requisitos mínimos siguiendo estándares
de desarrollo de buenas prácticas, haciendo que el código implementado se pueda mantener y
sostener por cualquier persona involucrada en el proyecto:
Usa tabulador, y en el caso de que uses espaciado, 4 espacios.
Comillas simples para strings, excepto cuando hay que escapar comillas simples dentro de la
cadena.
Después de cada sentencia usar un espaciado para facilitar la lectura.
Ejemplo: if (condición) {…}
No dejar variables zombis, variables definidas y no usadas.
Usar comparador de valor y tipo siempre que sea posible [===].
Dejar espacio entre operadores facilitando la lectura del código. Ejemplo: var x = 1;
En la declaración de parámetros/argumentos de funciones dejar un espacio tras la coma de
separación para facilitar la lectura.
Mantener las llaves de apertura en la misma línea de la condición. Ej.: if (cond) {
Mantener la sentencia ‘else’ en la misma línea del cierre del if.
Para condiciones simples no usar líneas nuevas, en tal caso abrir y cerrar llaves.
No dejar múltiples saltos de línea en blanco para la separación de código.
No asignes múltiples variables en la misma línea.
En la asignación de múltiples variables, no definas el estamento completo para cada una de
ellas, separa por coma y salto de línea.
Utilizar nombres descriptivos para las variables.
Escribe todos los puntos y comas (;) siempre que se deban llevar.
En ejecución, todas las declaraciones var y function son movidas para el comienzo de cada
función (su alcance) - esto es conocido como Elevación. Dicho esto, es buena práctica declarar
todas las variables juntas en la primera línea, con el fin de evitar falsas expectativas con las
variables que han sido declaradas luego de la asignación de su valor.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 22 de 47
Comenta el código para que se pueda mantener y sostener fácilmente.
Reduce el número de variables globales.
5.2. Creación de tarea de procesado JS
Como para JS no vamos a utilizar ningún lenguaje intérprete de JS, si no que vamos a utilizar
javascript estándar, no necesitamos ningún plugin para procesarlo. Únicamente necesitamos
disponer de una tarea que copie los archivos JS a nuestro directorio app:
gulp.task('js', function(){
return gulp.src('src/**/*.js')
.pipe(gulp.dest('app'));
});
Utilizamos las api de GULP SRC y DEST únicamente, indicando que recoja cualquier archivo JS
(aunque esté en subdirectorios) y copie la misma estructura a nuestra carpeta app.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 23 de 47
6. Procesando librerías de terceros
6.1. Instalación de USEREF
Debido a que el entorno se ha orientado para el trabajo con AngularJS y su metodología permite
crear múltiples archivos sin seguir una esctructura definida de los archivos, no vamos a utilizar los
plugins habituales de concatenación para unir nuestros JS. En su lugar utilizaremos el plugin gulp-
useref como alternativa a los mismos, ya que nos permite una flexibilidad a la hora de elegir cómo
generar el JS sin tener que modificar el archivo gulpfile, que otros plugins no permiten.
Para la instalación del paquete necesario para nuestra tarea ejecutamos el comando:
npm install gulp-useref --save-dev
6.2. Creación de tarea de procesado USEREF
El plugin USEREF depende explícitamente de ficheros HTML, por tanto debemos ejecutar ésta
tarea una vez hayamos compilado las plantillas PUG. Además, como useref está orientado a
minimizar los ficheros que generemos lo asociaremos a la tarea de distribución.
Para ello crearemos una tarea ‘dist’ que ejecute la tarea pug, sass, una vez que procese nuestras
fuentes, lanzamos la función que ejecuta useref sobre nuestro HTML generado.
gulp.task('dist', ['sass', 'pug'], function(){
return gulp.src('app/**/*.html')
.pipe(useref({searchPath: 'src'}))
.pipe(gulp.dest('app'));
});
El parámetro searchPath que le facilitamos a useref, indica dónde tiene que buscar si no encuentra
los archivos que está buscando. En nuestro caso cuando encuentre un JS o CSS que no esté en la
carpeta app lo buscará también dentro de la carpeta src.
Más adelante veremos por qué motivo hemos optado por este comportamiento y además
extenderemos ésta tarea, pues USEREF únicamente se encarga de concatenar archivos, no los
minimiza ni procesa de ninguna otra forma.
6.3. Instalación de librerías jquery y bootstrap mediante Bower
En apartados anteriores, hemos visto que Bower es un gestor de librerías externas, que nos permite
instalar las últimas versiones de las librerías y frameworks más extendidos, así no tenemos más que
lanzar un comando para instalar cualquiera de estas librerías. En nuestro caso y para seguir con el
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 24 de 47
ejemplo de la tarea de procesado USEREF, instalaremos jquery y bootstrap mediante los siguientes
comandos:
bower install jquery --save
bower install bootstrap --save
Con el parámetro --save especificamos que la librería que se instale se guarde como dependencia
en el proyecto.
6.4. Uso de build useref dentro del código HTML
El uso de USEREF es muy sencillo, únicamente tenemos que incluir los archivos que queremos
concatenar dentro de unos comentarios específicos, dependiendo de si es JS o CSS se forman de
la siguiente manera:
// build:css assets/css/vendor.css
link(rel='stylesheet', href='../bower_components/bootstrap/dist/css/bootstrap.min.css')
link(rel='stylesheet', href='../bower_components/bootstrap/dist/css/bootstrap-
theme.min.css')
// endbuild
// build:js assets/libs/vendor.js
script(src='../bower_components/jquery/dist/jquery.slim.min.js')
script(src='../bower_components/bootstrap/dist/js/bootstrap.min.js')
// endbuild
Al compilar nuestro pug nos genera una estructura como la siguiente:
<!-- build:TIPO archivo-de-salida -->
<!-- endbuild -->
Donde TIPO especificamos si va a concatenar un JS o CSS y en archivo de salida especificamos la
ruta y el nombre de archivo que nos va a generar.
Este comentario lo analiza USEREF cuando lo encuentra dentro del HTML y todo lo que haya
dentro del inicio y el fin del comentario lo concatenará en un archivo con la ruta y nombre que le
indiquemos. Así tenemos total control sobre cómo se generan estos archivos dentro del propio
código sin tener que modificar el archivo gulpfile.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 25 de 47
7. Automatización de HTML, CSS y JS
7.1. Instalación de Gulp Watch
Dado que la propia API Watch de GULP tiene algunos problemas a la hora de trabajar con archivos
que son añadidos en caliente en el proyecto, hemos optado por utilizar un plugin de terceros en
lugar de la propia api de gulp.
Para ello tenemos que instalar el paquete gulp-watch:
npm install gulp-watch --save-dev
7.2. Creación de tarea de escucha para el procesado automático de PUG, SASS y JS.
Tanto la api Watch de GULP como el plugin gulp-watch utilizan una invocación muy similar, ya que
le especificamos en qué ficheros va a escuchar y qué tarea va a ejecutar:
API GULP:
gulp.watch('*.scss', ['tarea-sass']);
Gulp Watch:
gulpwatch('*.scss', function(){
gulp.start('tarea-sass');
});
En nuestro caso, vamos a modificar la tarea default para que invoque a la tarea build y cuando haya
terminado, se quede escuchando los cambios sobre los archivos SASS, PUG y JS:
gulp.task('build', ['clean', 'sass', 'pug', 'js']);
gulp.task('default', ['build'], function(){
gulpwatch('src/**/*.scss', function(){
gulp.start('sass');
});
gulpwatch('src/**/*.pug', function(){
gulp.start('pug');
});
gulpwatch('src/**/*.js', function(){
gulp.start('js');
});
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 26 de 47
});
Para ello, con los tres escuchadores que hemos creado, cada vez que haya un cambio en nuestros
archivos fuente, se invocará a la tarea correspondiente dependiendo del tipo de archivo que se ha
modificado.
7.3. Corrección de errores en procesado de SASS
Cuando utilizamos el plugin gulp-sass y un editor de texto que no dispone de la opción de guardado
atómico (Atomic Save), nos encontramos con el problema de que en el momento que se ejecuta la
tarea SASS, el editor todavía no ha terminado de guardar los archivos que tiene que procesar y en
algunas ocasiones nos aparece un error de compilación porque no ha podido encontrar el sass
parcial que tiene que procesar.
Para solucionar este error, utilizaremos un plugin para añadir un delay a la tarea de procesado, en
este caso el plugin se llama gulp-wait y con el podremos añadir un tiempo de espera antes de que
procese la tarea SASS, así nos aseguramos que el editor ya ha guardado correctamente los
archivos antes de que sean procesados.
Para la instalación del plugin:
npm install gulp-wait --save-dev
Una vez instalado el plugin, modificamos la tarea SASS y añadimos el delayer de 100ms justo antes
de ejecutar la tarea sass():
gulp.task('sass', function(){
return gulp.src('src/**/!(_)*.scss')
.pipe(wait(100))
.pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
.pipe(gulp.dest('app'));
});
Con esto nos aseguramos que no aparezca el error cuando no encuentra los archivos parciales que
tiene que procesar.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 27 de 47
8. Servidor en vivo
8.1. Instalación de BrowserSync.
Una de las tareas más pesadas cuando estamos desarrollando es actualizar el navegador cada vez
que hacemos un cambio en el código.
BrowserSync, además de actualizar el navegador automáticamente, también sincroniza el scroll y
los clicks en todos los navegadores conectados, permitiendo sincronizar los movimientos a través
de la web en todos los dispositivos. Algo muy útil en el desarrollo y testeo.
También dispone de una interfaz gráfica que permite configurar la herramienta, consultar el historial,
sincronizar todos los dispositivos en la misma página de la aplicación, herramientas para hacer
debug, y más opciones.
BrowserSync no es un plugin de gulp específico, ya que soporta su utilización tanto en gulp como
grunt.
Para instalar el plugin BrowserSync:
npm install browser-sync --save-dev
Además, al declarar su variable, debemos hacerlo de la siguiente forma:
var browsersync = require('browser-sync').create()
8.2. Creación de tarea para servir estáticos.
La tarea para servir nuestros estáticos generados, es muy simple, sólo tenemos que especificar el
directorio app de nuestro proyecto y además añadir la ruta a la carpeta bower_components, ya que
éstos se encuentran fuera de la carpeta app y no tendríamos acceso directo desde el servidor, por
ello lo añadimos como ruta (alias).
gulp.task('serve', function(){
browsersync.init({
server: {
baseDir: 'app',
routes: {
'/bower_components': 'bower_components'
}
}
});
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 28 de 47
});
Añadimos la tarea serve a nuestro flujo de dependencias en la tarea build, para que cada vez que
ejecutemos gulp nos compile todos los fuentes y a su vez nos sirva el resultado en el navegador:
gulp.task('build', ['clean', 'sass', 'pug', 'js', 'serve']);
Una vez que el servidor comience a escuchar, nos informa de las URL’s de acceso en la consola
que ha lanzado la tarea, así podemos ver los puertos e IP’s de acceso local, remoto y a la UI de
configuración:
[BS] Access URLs:
-------------------------------------
Local: http://localhost:3000
External: http://10.111.98.32:3000
-------------------------------------
UI: http://localhost:3001
UI External: http://10.111.98.32:3001
-------------------------------------
[BS] Serving files from: app
Si por algún motivo, necesitamos cambiar los puertos de acceso al servidor y a la consola de
configuración, debemos especificar los puertos deseados en la propia tarea serve:
gulp.task('serve', function(){
browsersync.init({
port: 2016,
server: {
baseDir: 'app',
routes: {
'/bower_components': 'bower_components'
}
},
ui: {
port: 2017
}
});
});
En este ejemplo especificamos el Puerto 2016 para el servidor y el puerto 2017 para la consola de
browsersync.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 29 de 47
8.3. Testing de eventos multidispositivo mediante browsersync.
Por defecto BrowserSync arranca en modo multi dispositivo, por lo que si abrimos la url de nuestro
servidor en distintos dispositivos, todos los eventos que ejecutemos sobre cualquiera de los clientes
que acceden al servidor se trasladará al resto. Es decir, si abrimos desde un navegador de escritorio
y hacemos scroll sobre la página, en el resto de navegadores (móviles, tablets, pc, etc…) se clonará
éste comportamiento, y toda la navegación que vayamos realizando se traslada al resto de
dispositivos.
8.4. Configuración de consola BrowserSync.
En la consola de browsersync, podremos configurar distintas opciones y ver información sobre el
servidor que hemos lanzado. En la pestaña overview vemos la información de acceso al servidor, la
ruta que está sirviendo y las conexiones que hay establecidas en ese momento. Desde aquí
podemos mandar una orden de sincronizar el navegador de todas las conexiones.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 30 de 47
En la pestaña Sync Options podemos elegir qué eventos se van a sincronizar entre los distintos
dispositivos conectados a nuestro servidor:
La pestaña History nos mostrará las distintas rutas a las que han accedido los dispositivos.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 31 de 47
La pestaña Plugins nos permite configurar los plugins que hayamos cargado junto a browsersync.
La pestaña Remote Debug nos permite controlar distintas formas de hacer debug remoto sobre
nuestro servidor.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 32 de 47
Por último la pestaña Network Throttle nos permite simular varios tipos de conexión a nuestro
servidor, para poder comprobar cómo se comportaría nuestra aplicación bajo cada uno de estos
casos.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 33 de 47
9. Preparación del entorno para distribución y metodología
9.1. Minificado de librerías de terceros
En puntos anteriores, hemos visto como concatenar las librerías de terceros utilizando USEREF.
Ahora vamos a completar la tarea USEREF para que minimice el CSS y JS de terceros, utilizando
los plugins gulp-uglify y gulp-clean-css.
Instalamos los plugins que vamos a utilizar
npm install gulp-if --save-dev
npm install gulp-uglify --save-dev
npm install gulp-clean-css --save-dev
Como vamos a utilizar el resultado del pipe useref(), necesitamos discriminar de alguna forma los
ficheros resultantes, para aplicar sobre ellos los plugins correspondientes para el tipo de archivo
seleccionado. Por este motivo utilizamos el plugin gulp-if.
Ahora completamos la tarea dist y modificamos el pipe USEREF:
gulp.task('dist', ['clean', 'sass', 'pug'], function(){
return gulp.src('app/**/*.html')
.pipe(useref({searchPath: 'src'}))
.pipe(gulpif('*.js', uglify()))
.pipe(gulpif('*.css', minify()))
.pipe(gulp.dest('app'));
});
Si analizamos la tarea, podemos ver que utilizamos gulp-if para discriminar el tipo de archivo que
obtenemos del pipe USEREF, si obtenemos archivos JS los pasamos a la tarea uglify() y cuando
obtenemos archivos CSS los pasamos a la tarea minify(), ya que de otra forma no funcionaría y
provocaría un error en la tarea, puesto que uglify sólo puede aplicarse sobre archivos js y minify sólo
puede aplicarse sobre archivos css.
9.2. Creación de tareas de metodología
Debido a que queremos que el código que generemos sea óptimo y fiel a los estándares,
utilizaremos una serie de plugins que analizarán nuestro código y nos informarán de errores que
cometamos en caliente. Así podremos subsanarlos al mismo tiempo que estamos desarrollando.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 34 de 47
9.2.1. Metodología en CSS mediante CSSLint
Para asegurar un código CSS correcto, utilizamos la herramienta CSSLint que dispone de
una serie de reglas predefinidas para asegurar un desarrollo óptimo. Podemos consultar
éstas reglas en https://github.com/CSSLint/csslint/wiki/rules. Para su utilización necesitamos
instalar el plugin gulp-csslint:
npm install gulp-csslint --save-dev
Una vez instalado, añadimos el pipe con la tarea csslint después de generar el sass,
además debido a las características de nuestro desarrollo, inhabilitaremos un par de reglas
que no deseamos comprobar en nuestro desarrollo:
gulp.task('sass', function(){
return gulp.src('src/**/!(_)*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(csslint({
'order-alphabetical': false,
'box-model': false
}))
.pipe(csslint.formatter())
.pipe(browsersync.reload({stream:true}))
.pipe(gulp.dest('app'));
});
La más importante es que no compruebe el modelo de caja, ya que por defecto nuestro
proyecto incluye bootstrap y su reset.css, que especifica un modelo de caja a todos los
elementos HTML, por ello no los controlaremos en nuestro CSS, pues resultaría demasiado
redundante y con una carga más pesada.
Por otra parte, recomendamos encarecidamente el uso del plugin CSSComb para nuestro
editor, con una simple combinación de teclas formateará nuestro CSS de la forma más
óptima. Por ello inhabilitamos la regla de orden alfabético de declaraciones.
La instalación de CSSComb depende de cada editor, sólo hay que buscarlo en los
repositorios de plugins para cada uno de ellos e instalarlo. Si encuentra el archivo de
configuración en la raíz del proyecto utilizará las reglas predefinidas en el mismo para
formatear el código, esto lo hacemos pulsando la combinación de teclas:
Control + Shift + C .
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 35 de 47
9.2.2. Compatibilidad de CSS3 con Autoprefixer
Debido a que nuestra aplicación se desarrollará utilizando HTML5 y CSS3, no vamos a
preocuparnos de dar soporte a navegadores antiguos para las propiedades CSS3 utilizando
los vendor prefixes. En nuestro caso escribiremos el código CSS3 estándar y utilizaremos la
herramienta autoprefixer, para poder cambiar el soporte a navegadores antiguos
modificando la tarea de gulp, evitándonos tener que modificar nuestro código SASS.
Para ello instalamos el plugin gulp-autoprefixer:
npm install gulp-autoprefixer --save-dev
Básicamente utilizaremos el pipe autoprefixer justo después de que generemos el CSS, por
lo que lo añadiremos más adelante a la tarea SASS.
gulp.task('sass', function(){
return gulp.src('src/**/!(_)*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer({
Browsers: ['> 5%', 'firefox < 20']
}))
.pipe(csslint.formatter())
.pipe(browsersync.reload({stream:true}))
.pipe(gulp.dest('app'));
});
9.2.3. Metodología en JS mediante JSHint
Al igual que en CSS, también aplicaremos una serie de reglas sobre nuestro código
JavaScript para asegurar que utilizamos buenas prácticas en su desarrollo. Para ésta tarea
utilizaremos los plugins jshint y gulp-jshint (éste último es dependiente del primero):
npm install jshint --save-dev
npm install gulp-jshint --save-dev
Una vez instalados, modificaremos nuestra tarea JS, que como únicamente la ejecutaremos
en modo desarrollo no necesitamos distinguir la tarea que estamos ejecutando. En el punto
USEREF explicábamos por qué habíamos elegido éste comportamiento, ya que en
desarrollo nos interesa tener todos los JS separados para poder hacer debug más
fácilmente. En cambio, cuando entreguemos la distribución nos interesa concatenary
minificar todo el JS en un único archivo:
gulp.task('js', function(){
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 36 de 47
return gulp.src(['src/**/*.js', '!src/assets/libs/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(browsersync.reload({stream:true}))
.pipe(gulp.dest('app'));
});
Además modificaremos la entrada de archivos, para que ignore cualquier archive JS que se
encuentre dentro del directorio de librerías, ya que no nos interesa que procese éstos
archivos, que son de terceros y no hemos desarrollado nosotros. Esta misma cadena de
entrada la aplicaremos en la tarea Watcher de JS, para que no ejecute nuestra tarea js en
estos archivos.
gulpwatch(['src/**/*.js', '!src/assets/libs/*.js'], function(){
gulp.start('js');
});
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 37 de 47
9.3. Creación de tareas adicionales
9.3.1. Tareas de copiado de ficheros
Debido a que todos los archivos los tenemos en nuestra carpeta src, puesto que cada vez
que ejecutamos una tarea la carpeta app se limpia completamente y por lo tanto no
podríamos alojar archivos de imágenes, tipografías, etc… en esta carpeta. Necesitamos
crear una tarea de copiado para cada tipo de fichero que necesitamos copiar a nuestra
carpeta APP cuando se ejecutan las tareas iniciales o como veremos más adelante, cuando
se cambien ficheros y que ejecute el watcher.
Básicamente, vamos a comprobar cuando se añaden Imágenes, Librerías de terceros (CSS
y JS), Tipografías e Imágenes SVG (Estas últimas las copiamos aparte, porque para las
imágenes, además de copiar vamos a optimizarlas para ahorrar el máximo espacio posible).
Para ésta tarea, necesitamos instalar el plugin gulp-imagemin:
npm install gulp-imagemin --save-dev
Después conformaremos las tareas de la misma forma, indicando en algunas de ellas varias
extensiones para recoger los ficheros correspondientes:
gulp.task('copy:css', function(){
return gulp.src('src/assets/css/*.css')
.pipe(gulp.dest('app/assets/css/'));
});
gulp.task('copy:images', function(){
return gulp.src('src/assets/img/*.+(jpg|png|gif|jpeg)')
.pipe(imagemin({progressive: true}))
.pipe(gulp.dest('app/assets/img/'));
});
gulp.task('copy:fonts', function(){
return gulp.src('src/assets/fonts/*.+(eot|svg|ttf|woff|woff2|otf)')
.pipe(gulp.dest('app/assets/fonts'));
});
gulp.task('copy:libs', function(){
return gulp.src('src/assets/libs/*.js')
.pipe(gulp.dest('app/assets/libs/'));
});
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 38 de 47
gulp.task('copy:svg', function(){
return gulp.src('src/assets/img/*.svg')
.pipe(gulp.dest('app/assets/img/'));
});
Analizando las tareas, vemos que todas comparten una cierta estructura, en algunas de
ellas seleccionamos muy detalladamente las extensiones que queremos procesar, ya que
en alguna de estas carpetas podemos tener ejemplos o muestras de uso y no queremos
procesarlas. Al ser más explicitos en los ficheros de entrada, tenemos que ser igual de
explícitos en el destino, pues no nos va a generar la propia estructura si sólo indicásemos la
salida app.
En el caso de la tarea de copiado de imágenes, añadimos el pipe imagemin() con la opción
de guardado progresivo, para que ahorre tamaño en las imágenes sin que pierdan
demasiada calidad.
9.3.2. Tareas de limpiado de ficheros
Hemos creado una serie de tareas de copiado, como estas tareas no ejecutan ningún pipe
especial y sólo las vamos a utilizar para copiar en nuestra carpeta de desarrollo
necesitamos crear unas tareas de limpieza para que elimine los archivos que hayamos
eliminado de nuestra carpeta src.
Para la eliminación de archivos utilizaremos el plugin DEL de node, no es un plugin propio
de gulp, por lo que nuestras tareas no se formarán con la estructura propia de la api de gulp,
en su lugar sólo retornamos el comando del.sync('archivo/s');
Para la instalación del plugin:
npm install del --save-dev
Todas las tareas se conforman de la misma manera, sólo se aplican sobre cada tipo de
fichero concreto, a excepción de la tarea clean general que borra toda la carpeta app cada
vez que construimos en modo desarrollo o distribución:
gulp.task('clean', function(){
return del.sync(['app/*']);
});
gulp.task('clean:css', function(){
return del.sync(['app/assets/css/*.*', '!app/assets/css/main.css']);
});
gulp.task('clean:fonts', function(){
return del.sync('app/assets/fonts/*.*');
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 39 de 47
});
gulp.task('clean:images', function(){
return del.sync('app/assets/img/*.+(jpg|png|gif|jpeg)');
});
gulp.task('clean:libs', function(){
return del.sync('app/assets/libs/*.*');
});
gulp.task('clean:svg', function(){
return del.sync('app/assets/img/*.svg');
});
La única excepción se produce en la tarea de limpieza de CSS, pues no queremos que
elimine nuestro archivo procesado mediante SASS. En este caso le indicamos una negación
a nuestro archivo generado por SASS.
9.3.3. Watchers para copiado de ficheros
Como queremos procesar los cambios que hagamos en los ficheros indicados
anteriormente, no solo que los copie al inicio de nuestra tarea, necesitamos definir una serie
de watchers, que ejecutarán cada tarea de limpiado y copiado concreta.
Cada una de las tareas, ejecutará primero la limpieza de los archivos antiguos y copiará los
nuevos siempre que se produzcan cambios, así nos aseguramos de no dejar archivos
residuales en sus correspondientes directorios:
gulpwatch(['src/**/*.js', '!src/assets/libs/*.js'], function(){
gulp.start('js');
});
gulpwatch('src/assets/img/*.+(jpg|png|gif|jpeg)', function(){
gulp.start('clean:images');
gulp.start('copy:images');
});
gulpwatch('src/assets/fonts/*.+(eot|svg|ttf|woff|woff2|otf)', function(){
gulp.start('clean:fonts');
gulp.start('copy:fonts');
});
gulpwatch('src/assets/libs/*.js', function(){
gulp.start('clean:libs');
gulp.start('copy:libs');
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 40 de 47
});
gulpwatch('src/assets/css/*.css', function(){
gulp.start('clean:css');
gulp.start('copy:css');
});
gulpwatch('src/assets/img/*.svg', function(){
gulp.start('clean:svg');
gulp.start('copy:svg');
});
Como podemos observar, estamos utilizando la misma entrada de extensiones de archivo
que en las tareas de copiado y limpiado, para asegurarnos de limpiar únicamente las
extensiones que nos afectan y no eliminar archivos generados por otras tareas.
También hemos modificado la entrada de archivos de la tarea Watcher de JS, puesto que
ahora tenemos que tener en cuenta que podemos tener archivos JS dentro de la carpeta
LIBS y éstos JS no nos interesa ni procesarlos (Ya modificamos la tarea JS para evitar
procesar estos archivos), ni tan siquiera que ejecute la tarea, así nos evitamos ejecutar una
tarea que no va a hacer nada sobre éstos archivos innecesariamente. Para ello utilizamos la
condición de que no escuche cualquier archivo js dentro de la carpeta libs.
9.4. Completado de tareas de distribución
Ya tenemos creada la tarea dist, que creamos y dejamos aparcada en un punto anterior. Ahora
necesitamos completar las tareas que son llamadas desde dist para que generen contenido
minificado y optimizado para distribuir.
9.4.1. Completado de la tarea SASS
Ya que por defecto la tarea SASS nos devuelve el código CSS en formato expandido,
necesitamos modificar ésta tarea para que nos devuelva el código minificado si estamos
invocándola desde la tarea dist.
Para ello nos ayudamos del objeto gulp devuelto en cada ejecución de tarea y más
concretamente del array seq (this.seq) que nos devuelve un array con la secuencia de
tareas ejecutadas en la tarea actual. Como nuestra intención es comprobar cuándo estamos
en la tarea dist, buscaremos que ‘dist’ sea parte del resultado de this.seq, comprobando
que es parte del índice del array.
gulp.task('sass', function(){
if(this.seq.indexOf('dist') >= 0) {
return gulp.src('src/**/!(_)*.scss')
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 41 de 47
.pipe(sass({outputStyle:'compressed'}).on('error', sass.logError))
.pipe(autoprefixer({browsers: ['> 5%', 'firefox < 20']}))
.pipe(gulp.dest('app'));
} else {
return gulp.src('src/**/!(_)*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(csslint({'order-alphabetical': false, 'box-model': false}))
.pipe(csslint.formatter())
.pipe(browsersync.reload({stream:true}))
.pipe(gulp.dest('app'));
}
});
De esta forma comprobamos cuando estamos dentro de dist y ejecutamos sass en modo
comprimido y le añadimos los vendor prefixes correspondientes. De lo contrario ejecutamos
sass en modo expandido y además ejecutamos CSSLint para el análisis de errores.
9.4.2. Completado de la tarea COPY
Debido a que queremos que la tarea copy ejecute distintas subtareas dependiendo de si
estamos en modo desarrollo o modo distribución, utilizaremos la comprobación de
secuencia dist, para crear una pequeña función que sólo ejecute las subtareas de copiado
específicas de desarrollo cuando no estemos en modo dist, para ello modificaremos nuestra
tarea copy:
gulp.task('copy', function(){
gulp.start('copy:fonts');
gulp.start('copy:images');
gulp.start('copy:svg');
if(this.seq.indexOf('dist') < 0) {
gulp.start('copy:css');
gulp.start('copy:libs');
}
});
9.4.3. Creación de tarea DIST:TEST
Para poder ejecutar una aplicación angularjs, tenemos que utilizar un servidor, puesto que si
abrimos los ficheros html directamente en el navegador no funcionará, sería muy
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 42 de 47
conveniente disponer de una forma rápida de testear que el minimizado de CSS/JS no
afecta a nuestra aplicación y que todo funciona correctamente, creando la siguiente tarea:
gulp.task('dist:test', ['dist'], function(){
gulp.start('serve');
});
Simplemente añadimos una tarea dist:test que depende de dist y cuando dist finalice
ejecutará la tarea serve que arranca BrowserSync en el directorio app, que es el directorio
donde dist nos genera el distribuible por defecto.
9.4.4. Creación de tarea DIST:ZIP
Para finalizar y para facilitarnos la entrega a la hora de generar una distribución, vamos a
crear una tarea que genere la distribución y la comprima en un archivo ZIP con la fecha en
que se ha generado para entregarlo más fácilmente. Para poder crear el archivo ZIP,
necesitamos instalar el plugin gulp-zip:
npm install gulp-zip --save-dev
Después, creamos una tarea donde obtenemos la fecha actual del sistema y la añadimos al
nombre del archivo ZIP que vamos a generar:
gulp.task('dist:zip', ['dist'], function(){
var fechaCreacion = new Date().toLocaleDateString();
return gulp.src('app/**/*.*')
.pipe(zip('app-dist_'+fechaCreacion+'.zip'))
.pipe(gulp.dest('./'));
});
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 43 de 47
10. Creación de guía de estilos
10.1.Instalación del plugin y tareas gulp
Gracias a la tecnología provista mediante KSS, podemos incluir comentarios con un format
específico en nuestros ficheros CSS para ir construyendo una guía de estilos con los estilos propios
de nuestro SASS.
Guía de uso KSS: https://github.com/kneath/kss/blob/master/SPEC.md
De esta forma, ayudamos a construir una documentación visual de cómo hay que escribir el código
HTML para generar los distintos elementos que hemos estilizado mediante nuestro CSS.
Para esta tarea utilizamos el plugin sc5-styleguide compatible tanto con GulpJS como con
GruntJS. Este plugin funciona con AngularJS, por lo que para poder consultar la guía de estilos una
vez generada, tenemos que utilizar un servidor web, de lo contrario no podemos consultarla.
Para construir la guía de estilos necesitamos incluir un archivo Markdown con el texto de
introducción o instrucciones a mostrar en la página principal de la guía de estilos e ir especificando
las distintas secciones que compondrán dicha guía de estilos mediante nuestros archivos SASS. La
propia tarea de styleguide se encargará de analizar nuestros archivos fuentes y construir la
estructura de navegación y los estilos a mostrar dependiendo de nuestros archivos SASS.
Sintaxis de Markdown: http://markdown.es/sintaxis-markdown/
Para la instalación del plugin:
npm install sc5-styleguide --save-dev
Una vez instalado el plugin, crearemos dos subtareas necesarias para la construcción de la guía de
estilos y una tarea principal que invocará a estas dos subtareas y además, se encargará de lanzar
un servidor específico para la guía de estilos:
gulp.task('styleguide:generate', function(){
return gulp.src('src/assets/css/**/*.scss')
.pipe(styleguide.generate({
title: 'Guía de estilos de ejemplo',
extraHead: '<link rel="stylesheet" href="assets/css/vendor.css" />',
overviewPath: 'src/assets/css/styleguide.md'
}))
.pipe(gulp.dest('app/styleguide'));
});
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 44 de 47
gulp.task('styleguide:applystyles', function(){
return gulp.src([
'src/assets/css/main.scss',
'bower_components/bootstrap/dist/css/bootstrap.min.css'
])
.pipe(sass({errLogToConsole: true}))
.pipe(styleguide.applyStyles())
.pipe(gulp.dest('app/styleguide'));
});
gulp.task('styleguide', ['dist', 'styleguide:generate', 'styleguide:applystyles'],
function(){
browsersync.init({
server: {
baseDir: "app/styleguide",
routes: {
"/css": "app/assets/css"
}
}
});
});
En la tarea styleguide:generate, especificamos el título de la guía de estilos, el archivo markdown
con la introducción y además, nuestro archivo vendor.css para que cargue los estilos de terceros
que utilizamos en nuestro código, por ejemplo bootstrap.
Aparte de esto, también tenemos que cargar los estilos de bootstrap en la tarea
styleguide:generate, para que al combinar ambas tareas se muestren correctamente los estilos
bootstrap que modifiquemos, por lo demás utilizará nuestro fuente SASS para generar los estilos y
elementos.
Por último, creamos la tarea principal styleguide, que se encarga de ejecutar la distribución y las
subtareas styleguide para una vez terminado servir el resultado utilizando browsersync. Así
podemos consultar mas fácilmente la guía de estilos.
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 45 de 47
10.2.Creación de estructura y estilos mediante KSS
Los puntos que conforman la estructura de la guía de estilos se definen dentro de nuestros ficheros
SASS. Por norma general seguiremos la estructura recomendada en las buenas prácticas CSS que
hemos visto en puntos anteriores. De tal forma que tendremos una sección Global o Commons y
una sección de parciales o Views/Features.
En el primer archivo que carguemos de tipo común o parcial mediante @import en nuestro SASS
indicaremos el nombre del menú donde iremos incluyendo los distintos subniveles. En este ejemplo
lo hacemos con los comunes:
_commons.scss
// Commons
//
// Estilos comunes para todo el proyecto
//
// Styleguide 1.0
Aquí estamos definiendo el primer punto de la guía de estilos 'Commons' y aplicando la numeración
1.0 como raíz. Si añadimos cualquier subnivel dentro de Commons lo haremos indicando la
numeración 1.x:
_buttons.scss
// Botones
//
// Muestrario de estilos de botones de bootstrap
//
// .btn-custom - Botón personalizado
// .btn-primary - Bootstrap Primary
// .btn-success - Bootstrap Success
// .btn-info - Bootstrap Info
// .btn-warning - Bootstrap Warning
// .btn-danger - Bootstrap Danger
// .btn-link - Bootstrap Link
// .btn-default - Comportamiento estándar de botón de Bootstrap
//
// markup:
// <button class="btn {$modifiers}">
// Texto del botón
// </button>
//
// Styleguide 1.1
Con la estructura de comentarios anterior, estamos indicando todas las distintas clases disponibles
para nuestro elemento, en este caso los botones. Además le estamos indicando el código necesario
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 46 de 47
para generar correctamente los botones, así KSS se encargará de generar un botón con el código
que le especifiquemos por cada una de las clases disponibles que también hemos especificado:
Doc.: document.docx Título: Front-End - Herramientas y Entorno UXVersión: 1.6Fecha: 21/12/2016
Página 47 de 47
Top Related