Advertisement
  1. Web Design
  2. Gulp.js

Объединяем Pattern Lab c Gulp

Scroll to top
Read Time: 14 min

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

Работаете-ли вы, или ваша команда со стайлгайдами (styleguides, руководства стилей)? Есть-ли у вас документация к вашим модулям? Если нет, не переживайте. В данном туториале я покажу одну из возможностей, как улучшить продуктивность работы в команде. Мы рассмотрим концепции предложенные Brad Frost и Dave Olsen, используя Pattern Lab для создания стайлгайдов и настроим Gulp для обработки ресурсов. Давайте начнём!

Что такое Gulp?

Gulp.js - система сборки, в своей основе использующая стримы. Важная концепция данного инструмента - у вас есть стримы, для которых вы указываете различные действия, которые необходимо совершить над файлами. Это быстрее чем делать все действия вручную, сохраняет уйму времени и нервов. К примеру, в этом туториале мы пропустим все наши Sass файлы через так называемый pipe (процесс, поток, программный канал):

  • скомпилируем Sass в CSS,
  • объединим CSS файлы,
  • минифицируем результат,
  • и перенесём его в другое место

Чтобы узнать больше об основах Gulp, взгляните на путеводитель для начинающих от Kezz Bracey's - Командная строка в веб-дизайне: автоматизация с Gulp.

Что такое Pattern Lab?

Pattern Lab - концепция о создании систем атомного дизайна (atomic design systems); создание модулей вместо создания непосредственно страниц. Данная концепция определяет несколько составных частей:

  • атомы
  • молекулы
  • организмы
  • шаблоны
  • страницы

Вы начнёте с самого маленького элементы и со временем создадите более крупные части, пока не будут созданны целые страницы. Подобный подход сохранит вам время, позволит продуктивно взаимодействовать с другими членами команды, а также гарантирует цельную структуру.

Атомы

Атомы не могут быть разбиты на более мелкие составляющие.

Это самые простые блоки, включая фундаментальные теги (к примеру списки), цвета, шрифты, анимации и так далее.

Молекулы

Молекулы - группы различных элементов (атомов), которые функционируют вместе подобно единому модулю.

К примеру, тизер с заголовком, изображение, параграф, а также ссылка "Читать полностью". Одиночные элементы объединённые вместе представляют из себя молекулу; часть более сложной и крупной системы.

Организмы

Организмы - группы элементов (атомов и молекул) и работают подобно разделам, секциям вашего веб-сайта.

Представьте, к примеру, шапку сайта. Это более крупная система, построенная из молекул, таких как форма поиска и навигация, обе из которых были созданы из более мелких атомов.

patternlab header organismpatternlab header organismpatternlab header organism
Организм - шапка Pattern Lab, показан на маленьком экране

Изучите примеры интерфейса и почувствуйте что представляет из себя вся система.

Приступим к магии!

Теперь пришло время соединить обе этих системы и настроить рабочий процесс для вашей команды. Pattern Lab предоставит нам HTML и простые элементы интерфейса, Gulp же в свою очередь будет обрабатывать необходимые нам ресурсы.

Ключевые особенности:

  • Компиляция Sass (с помощью Libsass)
  • Сервер (Browser-Sync)
  • Livereload
  • Минификация (Javascript, CSS и изображений)
  • Развёртывание на удалённом сервере
    • Обновление номера версии
    • Теги
    • Отправка файлов и тегов в конечное место назначения (endpoint)
    • Отправка файлов с помощью rsync на сервер

Введение

Перед тем как использовать Gulp у вас должен быть установлен node.js, на компьютере. Если его нет, взгляните на статью Kezz Bracey - Командная строка для веб-дизайна: работа со сторонними библиотеками, там вы найдёте инструкции по установке.

Давайте начнём установив глобально Gulp.js. В терминале введите:

1
npm install gulp -g

Теперь нам надо клонировать репозиторий Patternlab, чтобы у нас была основа, с которой можно работать.

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

Далее нам нужно настроить задачи (tasks) в gulp файле. Создайте gulpfile.js в корне нашего проекта. После этого нам нужен конфигурационный файл, где мы указываем все пути, так что создайте в этой папке также build.config.json.

Помимо этого нам понадобятся следующие файлы:

  • .bowerrc
  • package.json
  • bower.json

После всех начальных шагов, мы будем обладать основной структурой нашего проекта. Теперь давайте начнём описывать необходимые нашему рабочему процессу задачи.

Начнём с Gulpfile

На верху файла gulpfile.js мы запрашиваем (require) каждую зависимость. После установки плагина, вам нужно "запросить" его и дать ему имя.

Начнём с gulp и нашего файла конфигурации, в котором указаны все пути и настройки.

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

Во время процесса разработки нам не нужно минифицировать код (это пустая трата времени до тех пор, пока мы не будем готовы отправлять проект на сервер). Благодаря переменной production мы можем включать и выключать определённые задачи. Позже вы увидите это в действии.

1
// Production Handling

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

3
// Toggle minifing and optimization for assets

4
var production;

Теперь когда всё настроено, мы можем начать описывать задачи, которые помогут нам во время разработки!

Задача 1: отчистка всех ресурсов 

1
// Install needed dependency

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

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

Если удалить изображение из папки "source/", можно заметить что в папке "public/" также есть копия данного изображения. По причине подобного дублирования, нам нужно выполнить небольшие шаги, чтобы убрать изображение из "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
});

Задача 2: обработка скриптов

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');

При переносе проекта на сервер, важно иметь лишь один файл со всеми скриптами. Для этого мы используем плагин под названием gulp-concat и объединим все скрипты в application.js файл. Если переменная production равна true, тогда application.js будет минифицирован и получит новое имя: 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
});

Задача 3: шрифты

Эта задача отправит все шрифты в папку public. И ничего больше.

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
});

Задача 4: изображения

Для этого шага нам понадобится плагин gulp-imagemin. Как только мы его запросим, можно будет его использовать для сжатия изображений. Данная задача уменьшит размер изображения и положительно повлияет на производительность.

1
// Install imagemin

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

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

Если переменная production равна true, в этом случае все изображения будут сжаты. После того как это будет сделано, мы перенесём их в конечную папку.

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
});

Задача 5: обработка Sass

Давайте установим и добавим зависимости gulp-sass и 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');

Теперь мы возьмём все файлы, используем плагин Sass для компиляции их в CSS, после чего, если переменная production равна true, cssmin выполнит свою работу.

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
});

Задача 6: сервер Pattern Lab

У Pattern Lab есть собственный сервер, который можно запустить простой командой. Для запуска данной команды нам понадобится плагин gulp-shell.

1
// Install needed dependencies

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

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

На этом этапе мы скопируем папку styleguide из core в public. Теперь вы сможете увидеть в браузере целостный фронтенд.

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
});

Задача 7: запуск сервера и отслеживание файлов

Pattern Lab имеет встроенный сервер, но Browser-Sync меняет CSS без перезагрузки страницы.

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');

Watch позаботится об отслеживании изменений и будет запускать определённые задачи. После этого browser-sync обновит страницу в браузере.

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
});

Мы указали файлы для watch и указали необходимые задачи, которые сработают во время события изменения файлов.

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
});

Задача 8: задача по умолчанию

После запуска команды gulp в командной строке будет запущена задача по умолчанию. Но перед тем как Gulp запустит её, будет произведена отчистка (clean:before), тем самым будет удалены файлы в папке public.

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
});

Задача 9: начальный процесс

Давайте создадим задачу для создания стайлгайда, без минификации ресурсов. Будет запущен browser-sync, обработаны все ресурсы, после чего запустится отслеживание изменений файлов.

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
});

Задача 10: публикация и теги

Для этой задачи нам потребуются несколько новых плагинов.

  • Плагин gulp-bump для обновления номера версии.
  • gulp-filter позволит вам получить определённый файл из стрима
  • gulp-git позволяет использовать git команды в gulp
  • И gulp-tag-version для генерации тега.
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');

Теперь мы опишем gulp-task под названием release, зададим переменную production равную true (в данном случае потребуется минификация) и откроем стрим. Необходимо взять все файлы с номером версии, использовать плагин bump, также указать тип версии (patch, minor или major) с помощью параметра командной строки.

Если выполнить release-task без типа версии, тогда gulp-bump выдаст - x.x.1. После этого мы перенесём файлы в корень проекта и закоммитим изменения. Теперь пришло время сгенерировать новый тег проекта. В этом случае потребуется файл package.json, чтобы получить текущую версию для нового тега.

Ну и наконец, мы отправим все файлы и теги в репозиторий origin, используя какую захочется ветку.

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
});

Задача 11: развёртывание на сервере

Мы можем отправить все файлы на сервер с помощью rsync; данный подход очень быстр и удобен. Введите gulp deploy в терминале и после нескольких секунд, ваш локальный проект окажется на сервере. Не нужно вручную перетаскивать файлы и папки. Следует всё что можно автоматизировать. Хост и путь к папке, которую хотите отправить на сервер в 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
});

Конечный Gulpfile

Вы написали так много кода и вот вам финальный результат! Если захотите можно поместить каждую задачу в отдельный файл. Чтобы не усложнять, в данном туториале мы описали все задачи в одном 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
});

Файл конфигурации

Теперь укажем необходимые пути в файле с конфигурацией. Данный файл служит в качестве указателя путей и различных настроек проекта:

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
}

Заключение

Я люблю работать с комбинацией Gulp и Pattern Lab. Мне довелось работать в различных командах и создавать подобную основу для каждого проекта. Отзывы от других членов команды всегда были положительны в связи с простотой данного процесса. Каждый может воспользоваться цельной основой проекта, выбрать необходимый модуль и использовать его. Для отзывов и вопросов используйте форму для комментариев ниже.

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.