Advertisement
  1. Web Design
  2. Gulp.js

Combinando Pattern Lab con Gulp para mejorar el flujo de trabajo

Scroll to top
Read Time: 15 min

() translation by (you can also view the original English article)

¿Tu y tu equipo trabajan con guías de estilo? ¿Tienes documentación para tus módulos? Si no, no te asustes. En este tutorial, te mostraré cómo es posible mejorar la forma en que trabajas con tu equipo. Exploraremos los conceptos sugeridos por Brad Frost y Dave Olsen, usando Pattern Lab para crear guías de estilo, con Gulp para manejar los recursos. ¡Vamos a empezar!

¿Que es Gulp?

Gulp.js es un sistema de compilación en tiempo real y un ejecutor de tareas. El concepto importante es que tienes secuencias en las que defines muchas cosas para tus archivos. Es más rápido que manejar las cosas manualmente, ahorrándote los nervios y mucho tiempo. Por ejemplo, en este tutorial pondremos todos nuestros archivos Sass en una tubería (un proceso):

  • compilando Sass a CSS,
  • concatenando los archivos CSS,
  • minimizando la salida,
  • y moviéndolo todo a otra ubicación

Para obtener más información sobre los conceptos básicos de Gulp, consulta la guía para principiantes de Kezz Bracey, La línea de comandos para el diseño web: automatización con Gulp.

¿Que es Pattern Lab?

Pattern Lab es un concepto para crear sistemas de diseño atómico; construyendo módulos en lugar de construir páginas directamente. Define varias partes compuestas:

  • Átomos
  • Moléculas
  • Organismos
  • Plantillas
  • Páginas

Comienza con el elemento más pequeño, construyendo partes más grandes, hasta que tengas páginas completas. Combining Pattern Lab with Gulp for Improved Workflow

Átomos

Los átomos no se pueden dividir en piezas más pequeñas.

Estos son los bloques más simples, que incluyen etiquetas fundamentales como listas, colores, fuentes, animaciones, etc.

Moléculas

Las moléculas son grupos de diferentes elementos (átomos) que funcionan juntos como una unidad.

Por ejemplo, un teaser con un título, una imagen, un párrafo y un enlace como "Leer más". Cada uno de estos es un elemento único, pero juntos se convierten en una molécula; parte de un sistema más grande, más complejo.

Organismos

Los organismos son grupos de elementos (átomos y moléculas) y funcionan como una sección en tu sitio web.

Pensemos, por ejemplo, en un encabezado de página web. Es un sistema más grande, construido a partir de moléculas como un formulario de búsqueda y navegación, que a su vez están construidos con átomos más pequeños.

patternlab header organismpatternlab header organismpatternlab header organism
Organismo de Titulo Pattern Lab, visto en una pantalla pequeña.

Echa un vistazo a los demos de UI en línea y experimenta todo el sistema.

¡Que la magia suceda!

Ahora es el momento de combinar ambos sistemas y crear un flujo de trabajo para tu equipo. Pattern Lab nos proporcionará nuestro HTML y entregará la interfaz de usuario simple, Gulp manejará todos los recursos que necesitamos.

Nuestras características clave:

  • Compilación de Sass (Libsass)
  • Servidor (Browser-Sync)
  • Livereload
  • Minificación (Javascript, CSS and images)
  • Liberación/Despliegue
    • Aumento de la versión
    • Etiquetado
    • Empuje de archivos y etiquetas al punto final
    • Empuje de archivos vía rsync a un servidor

Introducción

Para usar Gulp, primero necesitas tener node.js en tu sistema. Si no es así, echa un vistazo a la Línea de Comandos para el Diseño Web de Kezz Bracey: Control de Paquetes de Terceros para obtener instrucciones de configuración.

Comencemos instalando Gulp.js globalmente. Escribe en el terminal:

1
npm install gulp -g

Ahora necesitamos clonar el repositorio de Patternlab para darnos una base para trabajar.

1
git clone git@github.com:pattern-lab/patternlab-php.git

A continuación necesitamos un archivo gulp para configurar nuestras tareas. Crea un gulpfile.js en la carpeta raíz de tu proyecto. Después de eso necesitamos un archivo de configuración, donde definimos todas las rutas, así que creamos un build.config.json en tu carpeta.

Los siguientes archivos también son necesarios:

  • .bowerrc
  • package.json
  • bower.json

Después de todos estos pasos básicos, tenemos la estructura básica del proyecto. Ahora comencemos a construir las tareas para nuestro flujo de trabajo.

Comienza con el Gulpfile

En la parte superior de nuestro archivo gulpfile.js, requerimos cada dependencia. Si instalas un complemento, debes "solicitarlo" y asignarle un nombre.

Comienza con gulp y nuestro archivo de configuración para todas las rutas y la configuración.

1
var gulp        = require('gulp'),
2
    config      = require('./build.config.json');

Durante nuestro proceso de desarrollo no tendremos que estar modificando nuestro código (es una pérdida de tiempo a menos que estemos listos para implementar). Con la siguiente variable de production podemos activar y desactivar algunas tareas. Verás esto en acción más adelante.

1
// Production Handling

2
// Description: Use 'production' variable with 'gulpif'

3
// Toggle minifing and optimization for assets

4
var production;

¡Con las cosas configuradas, ahora podemos comenzar a agregar varias tareas para ayudarnos en nuestro desarrollo!

Tarea 1: limpiar todos los recursos

1
// Install needed dependency

2
npm install gulp-clean
3
4
// Require dependency

5
var clean = require('gulp-clean');

Si eliminas una imagen de la carpeta "source/", encontrarás que hay una copia de la imagen en "public/" también. Debido a esta duplicación, realizaremos un paso simple para limpiar la carpeta de imágenes en "public/".

1
// Task: Clean:before

2
// Description: Removing assets files before running other tasks

3
gulp.task('clean:before', function () {
4
  return gulp.src(
5
    config.assets.dest
6
  )
7
    .pipe(clean({
8
      force: true
9
    }))
10
});

Tarea 2: Manejar Scripts

1
// Install needed dependencies

2
npm install gulp-concat gulp-uglify gulp-rename
3
4
// Require dependencies

5
var concat = require('gulp-concat');
6
var uglify = require('gulp-uglify');
7
var rename = require('gulp-rename');

Para fines de implementación, es importante tener un solo archivo con todos los scripts. Para lograr esto, usaremos el complemento gulp-concat y combinaremos todos nuestros scripts para producir application.js. Si la variable production es verdadera, entonces application.js será uglified y obtendrás un nuevo nombre: application.min.js.

1
gulp.task('scripts', function () {
2
  return gulp.src(config.scripts.files)
3
    .pipe(concat(
4
      'application.js'
5
    ))
6
    .pipe(gulpif(production, uglify()))
7
    .pipe(gulpif(production, rename({
8
      suffix: '.min'
9
    })))
10
    .pipe(gulp.dest(
11
      config.scripts.dest
12
    ))
13
    .pipe(browserSync.reload({stream:true}));
14
});

Tarea 3: Fuentes

Esta tarea empujará todas las fuentes a la carpeta pública. Nada mas.

1
// Task: Handle fonts

2
gulp.task('fonts', function () {
3
  return gulp.src(config.fonts.files)
4
    .pipe(gulp.dest(
5
      config.fonts.dest
6
    ))
7
    .pipe(browserSync.reload({stream:true}));
8
});

Tare 4: Imagenes

Para este paso instalaremos y requeriremos el complemento gulp-imagemin. Una vez que hayamos hecho eso, podemos usarlo para minimizar las imágenes. Esto ahorrará memoria y aumentará el rendimiento.

1
// Install imagemin

2
npm install gulp-imagemin
3
4
// Require dependencies

5
var imagemin = require('gulp-imagemin');

Si la variable production de es verdadera, entonces todas las imágenes serán minimizadas. Con eso hecho, los empujamos a la carpeta de destino.

1
// Task: Handle images

2
gulp.task('images', function () {
3
  return gulp.src(config.images.files)
4
    .pipe(gulpif(production, imagemin()))
5
    .pipe(gulp.dest(
6
      config.images.dest
7
    ))
8
    .pipe(browserSync.reload({stream:true}));
9
});

Tarea 5: Manejar Sass

Instalamos y requerimos las dependencias gulp-sass y gulp-cssmin.

1
// Install needed dependencies

2
npm install gulp-sass gulp-cssmin
3
4
// Require dependencies

5
var sass = require('gulp-sass');
6
var cssmin = require('gulp-cssmin');

Ahora tomaremos todos los archivos de Sass, usaremos el complemento de Sass para compilarlos en CSS, luego, si la variable production es verdadera, cssmin hará lo suyo.

1
// Task: Handle Sass and CSS

2
gulp.task('sass', function () {
3
  return gulp.src(config.scss.files)
4
    .pipe(sass())
5
    .pipe(gulpif(production, cssmin()))
6
    .pipe(gulpif(production, rename({
7
      suffix: '.min'
8
    })))
9
    .pipe(gulp.dest(
10
      config.scss.dest
11
    ))
12
    .pipe(browserSync.reload({stream:true}));
13
});

Tarea 6: Servidor Pattern Lab

Pattern Lab tiene su propio servidor, que puedes comenzar con un simple comando de shell. Para ejecutar este comando necesitamos el complemento gulp-shell

1
// Install needed dependencies

2
npm install gulp-shell
3
4
// Require dependencies

5
var shell = require('gulp-shell');

En este punto, copiaremos la carpeta styleguide del núcleo a público. En este punto, podrás ver un front-end sólido en el navegador.

1
// Task: patternlab

2
// Description: Build static Pattern Lab files via PHP script

3
gulp.task('patternlab', function () {
4
  return gulp.src('', {read: false})
5
    .pipe(shell([
6
      'php core/builder.php -gpn'
7
    ]))
8
    .pipe(browserSync.reload({stream:true}));
9
});
10
11
// Task: styleguide

12
// Description: Copy Styleguide-Folder from core/ to public

13
gulp.task('styleguide', function() {
14
  return gulp.src(config.patternlab.styleguide.files)
15
    .pipe(gulp.dest(config.patternlab.styleguide.dest));
16
});

Tarea 7: Iniciar servidor y ver archivos

Pattern Lab tiene un servidor incorporado, pero Browser-Sync maneja la inyección de cambios de CSS sin recargar la página.

1
// Install needed dependencies

2
npm install browser-sync gulp-watch
3
4
// Require dependencies

5
var browser-sync = require('browser-sync');
6
var watch = require('gulp-watch');

El observador se encarga de los cambios y activa las tareas específicas. Después de eso, la sincronización del navegador actualiza nuestra vista en el navegador.

1
// task: BrowserSync

2
// Description: Run BrowserSync server with disabled ghost mode

3
gulp.task('browser-sync', function() {
4
  browserSync({
5
    server: {
6
        baseDir: config.root
7
    },
8
    ghostMode: true,
9
    open: "external"
10
  });
11
});

Especificamos los archivos para el observador y activamos las tareas que necesitamos en caso de un cambio.

1
// Task: Watch files

2
gulp.task('watch', function () {
3
4
  // Watch Pattern Lab files

5
  gulp.watch(
6
    config.patternlab.files,
7
    ['patternlab']
8
  );
9
10
  // Watch scripts

11
  gulp.watch(
12
    config.scripts.files,
13
    ['scripts']
14
  );
15
  
16
  // Watch images

17
  gulp.watch(
18
    config.images.files,
19
    ['images']
20
  );
21
22
  // Watch Sass

23
  gulp.watch(
24
    config.scss.files,
25
    ['sass']
26
  );
27
28
  // Watch fonts

29
  gulp.watch(
30
    config.fonts.files,
31
    ['fonts']
32
  );
33
});

Tarea 8: Tarea por defecto

Escribe gulp en el disparador shell para la tarea predeterminada. Pero antes de que Gulp inicie esto, disparara la tarea clean:before de limpiar todos los archivos públicos.

1
// Task: Default

2
// Description: Build all stuff of the project once

3
gulp.task('default', ['clean:before'], function () {
4
  production = false;
5
6
  gulp.start(
7
    'patternlab',
8
    'styleguide',
9
    'fonts',
10
    'sass',
11
    'images',
12
    'scripts'
13
  );
14
});

Tarea 9: Iniciar proceso

Vamos a crear una tarea para desarrollar en la guía de estilo, pero sin minimizar los recursos. Esto desencadena la sincronización con el navegador, construye todos los activos e inicia el observador.

1
// Task: Start your production-process

2
// Description: Typ 'gulp' in the terminal

3
gulp.task('serve', function () {
4
  production = false;
5
6
  gulp.start(
7
    'browser-sync',
8
    'default',
9
    'watch'
10
  );
11
});

Tarea 10: Liberación y etiquetado

Para este paso necesitaremos algunos complementos nuevos.

  • El complemento gulp-bump es para actualizar el número de versión.
  • gulp-filter nos dará un archivo específico de la secuencia.
  • gulp-git nos permite usar enunciados git en gulp.
  • Y gulp-tag-version es para generar la etiqueta.
1
// Install needed dependencies
2
npm install gulp-bump gulp-filter gulp-git gulp-tag-version
3
4
// Require dependencies
5
var bump = require('gulp-bump');
6
var filter = require('gulp-filter');
7
var git = require('gulp-git');
8
var tagversion = require('gulp-tag-version');

Ahora define el release de gulp-task, establece la variable production en true (ahora necesitamos minimizar) y abrir la secuencia. Debes tomar todos los archivos con un número de versión, usar el complemento del plugin y hacer posible definir el tipo (parche, menor o mayor) a través de un parámetro en el shell.

Si ejecutas la tarea release sin escribir luego, gulp-bump tomarás un parche - x.x.1. Después de esto, empujas los archivos a la raíz y confirmas los cambios. Ahora es el momento de generar una nueva etiqueta para el proyecto. El archivo package.json es necesario para obtener el número de versión actual de la nueva etiqueta.

Finalmente, enviamos todos los archivos y etiquetas al origen y a la rama que queramos.

1
// Function: Releasing (Bump & Tagging)
2
// Description: Bump npm versions, create Git tag and push to origin
3
gulp.task('release', function () {
4
  production = true;
5
6
  return gulp.src(config.versioning.files)
7
    .pipe(bump({
8
      type: gulp.env.type || 'patch'
9
    }))
10
    .pipe(gulp.dest('./'))
11
    .pipe(git.commit('Release a ' + gulp.env.type + '-update'))
12
13
    // read only one file to get version number
14
    .pipe(filter('package.json'))
15
16
    // Tag it
17
    .pipe(tagversion())
18
19
    // Publish files and tags to endpoint
20
    .pipe(shell([
21
      'git push origin develop',
22
      'git push origin --tags'
23
    ]));
24
});

Tarea 11: Despliegue

Es posible desplegar todos los archivos en un servidor a través de rsync; Hacerlo es super rápido y cómodo. Escribe gulp deploy en tu terminal y después de unos segundos tendrás el proyecto local en el servidor. No es necesario arrastrar y soltar carpetas manualmente. Automatiza todas las cosas. Define el host y la ruta de la carpeta, que quieres desplegar en build.config.js.

1
// Task: Deploy static content
2
// Description: Deploy static content using rsync shell command
3
gulp.task('deploy', function () {
4
  return gulp.src(config.deployment.local.path, {read: false})
5
    .pipe(shell([
6
      'rsync '+ config.deployment.rsync.options +' '+ config.deployment.local.path +'/ '+ config.deployment.remote.host
7
    ]))
8
});

Archivo Gulp final

¡Has escrito tanto código, y aquí está el resultado final! Es posible que prefieras tener un archivo separado para cada tarea, en cuyo caso puedes dividirlo. En este caso, por simplicidad, mostraremos todo en un solo archivo Gulp:

1
var gulp        = require('gulp'),
2
    bump        = require('gulp-bump'),
3
    clean       = require('gulp-clean'), 
4
    concat      = require('gulp-concat'),
5
    browserSync = require('browser-sync'),
6
    cssmin      = require('gulp-cssmin'),
7
    filter      = require('gulp-filter'),
8
    git         = require('gulp-git'),
9
    gulpif      = require('gulp-if'),
10
    imagemin    = require('gulp-imagemin'),
11
    rename      = require('gulp-rename'),
12
    sass        = require('gulp-sass'),
13
    shell       = require('gulp-shell'),
14
    tagversion  = require('gulp-tag-version'),
15
    uglify      = require('gulp-uglify'),
16
    config      = require('./build.config.json');
17
18
// Trigger

19
var production;
20
21
// Task: Clean:before

22
// Description: Removing assets files before running other tasks

23
gulp.task('clean:before', function () {
24
  return gulp.src(
25
    config.assets.dest
26
  )
27
    .pipe(clean({
28
      force: true
29
    }))
30
});
31
32
// Task: Handle scripts

33
gulp.task('scripts', function () {
34
  return gulp.src(config.scripts.files)
35
    .pipe(concat(
36
      'application.js'
37
    ))
38
    .pipe(gulpif(production, uglify()))
39
    .pipe(gulpif(production, rename({
40
      suffix: '.min'
41
    })))
42
    .pipe(gulp.dest(
43
      config.scripts.dest
44
    ))
45
    .pipe(browserSync.reload({stream:true}));
46
});
47
48
// Task: Handle fonts

49
gulp.task('fonts', function () {
50
  return gulp.src(config.fonts.files)
51
    .pipe(gulp.dest(
52
      config.fonts.dest
53
    ))
54
    .pipe(browserSync.reload({stream:true}));
55
});
56
57
// Task: Handle images

58
gulp.task('images', function () {
59
  return gulp.src(config.images.files)
60
    .pipe(gulpif(production, imagemin()))
61
    .pipe(gulp.dest(
62
      config.images.dest
63
    ))
64
    .pipe(browserSync.reload({stream:true}));
65
});
66
67
// Task: Handle Sass and CSS

68
gulp.task('sass', function () {
69
  return gulp.src(config.scss.files)
70
    .pipe(sass())
71
    .pipe(gulpif(production, cssmin()))
72
    .pipe(gulpif(production, rename({
73
      suffix: '.min'
74
    })))
75
    .pipe(gulp.dest(
76
      config.scss.dest
77
    ))
78
    .pipe(browserSync.reload({stream:true}));
79
});
80
81
// Task: patternlab

82
// Description: Build static Pattern Lab files via PHP script

83
gulp.task('patternlab', function () {
84
  return gulp.src('', {read: false})
85
    .pipe(shell([
86
      'php core/builder.php -gpn'
87
    ]))
88
    .pipe(browserSync.reload({stream:true}));
89
});
90
91
// Task: styleguide

92
// Description: Copy Styleguide-Folder from core/ to public

93
gulp.task('styleguide', function() {
94
  return gulp.src(config.patternlab.styleguide.files)
95
    .pipe(gulp.dest(config.patternlab.styleguide.dest));
96
});
97
98
// task: BrowserSync

99
// Description: Run BrowserSync server with disabled ghost mode

100
gulp.task('browser-sync', function() {
101
  browserSync({
102
    server: {
103
        baseDir: config.root
104
    },
105
    ghostMode: true,
106
    open: "external"
107
  });
108
});
109
110
// Task: Watch files

111
gulp.task('watch', function () {
112
113
  // Watch Pattern Lab files

114
  gulp.watch(
115
    config.patternlab.files,
116
    ['patternlab']
117
  );
118
119
  // Watch scripts

120
  gulp.watch(
121
    config.scripts.files,
122
    ['scripts']
123
  );
124
125
  // Watch images

126
  gulp.watch(
127
    config.images.files,
128
    ['images']
129
  );
130
131
  // Watch Sass

132
  gulp.watch(
133
    config.scss.files,
134
    ['sass']
135
  );
136
137
  // Watch fonts

138
  gulp.watch(
139
    config.fonts.files,
140
    ['fonts']
141
  );
142
});
143
144
// Task: Default

145
// Description: Build all stuff of the project once

146
gulp.task('default', ['clean:before'], function () {
147
  production = false;
148
149
  gulp.start(
150
    'patternlab',
151
    'styleguide',
152
    'fonts',
153
    'sass',
154
    'images',
155
    'scripts'
156
  );
157
});
158
159
// Task: Start your production-process

160
// Description: Typ 'gulp' in the terminal

161
gulp.task('serve', function () {
162
  production = false;
163
164
  gulp.start(
165
    'browser-sync',
166
    'default',
167
    'watch'
168
  );
169
});
170
171
// Task: Deploy static content

172
// Description: Deploy static content using rsync shell command

173
gulp.task('deploy', function () {
174
  return gulp.src(config.deployment.local.path, {read: false})
175
    .pipe(shell([
176
      'rsync '+ config.deployment.rsync.options +' '+ config.deployment.local.path +'/ '+ config.deployment.remote.host
177
    ]))
178
});
179
180
// Function: Releasing (Bump & Tagging)

181
// Description: Bump npm versions, create Git tag and push to origin

182
gulp.task('release', function () {
183
  production = true;
184
185
  return gulp.src(config.versioning.files)
186
    .pipe(bump({
187
      type: gulp.env.type || 'patch'
188
    }))
189
    .pipe(gulp.dest('./'))
190
    .pipe(git.commit('Release a ' + gulp.env.type + '-update'))
191
192
    // read only one file to get version number

193
    .pipe(filter('package.json'))
194
195
    // Tag it

196
    .pipe(tagversion())
197
198
    // Publish files and tags to endpoint

199
    .pipe(shell([
200
      'git push origin develop',
201
      'git push origin --tags'
202
    ]));
203
});

Archivo de configuración

Ahora necesitamos nuestro archivo de configuración para establecer las diversas rutas. Este archivo es necesario para mantener las rutas y la configuración del proyecto:

1
{
2
  "root": "./public",
3
  "deployment": {
4
    "local": {
5
      "path": "public"
6
    },
7
    "remote": {
8
      "host": "YOUR HOST"
9
    },
10
    "rsync": {
11
      "options": "-avzh --delete -e ssh"
12
    }
13
  },
14
  "assets": {
15
    "base": "source/assets/",
16
    "dest": "public/assets/"
17
  },
18
  "versioning": {
19
    "files": [
20
      "./package.json",
21
      "./bower.json"
22
    ]
23
  },
24
  "scripts": {
25
    "base"  : "source/assets/javascripts/",
26
    "files" : [
27
      "source/assets/javascripts/**/*.js"
28
    ],
29
    "dest"  : "public/assets/javascripts/"
30
  },
31
  "components": {
32
    "base": "source/assets/components/"
33
  },
34
  "scss": {
35
    "base" : "source/assets/scss/",
36
    "files": [
37
      "source/assets/scss/**/*.scss"
38
    ],
39
    "dest" : "public/assets/stylesheets/"
40
  },
41
  "fonts": {
42
    "base" : "source/assets/fonts/",
43
    "files": [
44
      "source/assets/fonts/**/*"
45
    ],
46
    "dest" : "public/assets/fonts/"
47
  },
48
  "images": {
49
    "base" : "source/assets/images/",
50
    "files": [
51
      "source/assets/images/**/*"
52
    ],
53
    "dest" : "public/assets/images/"
54
  },
55
  "patternlab": {
56
    "styleguide": {
57
      "files": [
58
        "core/styleguide/**"
59
      ],
60
      "dest": "public/styleguide/"
61
    },
62
    "files": [
63
      "source/_patterns/**/*.mustache",
64
      "source/_patterns/**/*.json",
65
      "source/_data/*.json"
66
    ]
67
  }
68
}

Conclusión

Me encanta trabajar con una combinación de Gulp y Pattern Lab. He trabajado en diferentes equipos y he establecido esta base para cada proyecto. La retroalimentación de cada miembro del equipo siempre ha sido positiva debido a su proceso fácil de seguir. Todos tienen una superficie sólida, pueden escoger el módulo y usarlo con facilidad. Para preguntas o comentarios, por favor ve la sección de comentarios debajo.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.