Gulp — сборщик проекта, который на первый вгляд может показаться усложненным. Но как только Вы немного погрузитесь в него, то поразитесь, насколько он удобен и гибок для подстройки именно под Вашу структуру.
В этой статье мы разберем простой пример настройки Gulp и его плагинов, делается это через gulpfile.js в корне проекта. Установка самого сборщика и его плагинов осуществляется через пакетный менеджер npm.
Что мы используем в обычном проекте?
В простом проекте по верстке, в котором у нас будет папка исходников (src) и рабочего проекта (dist), мы работаем с:
- HTML — в нашем случае все будет в различных .html файлах двух типов: страницы и темплейты компонентов (здесь мы будем использовать плагин gulp-file-include, что очень сильно облегчает разработку и соответствует DRY);
- SASS/SCSS — будем использовать препроцессоры для удобства, те собирать будем все .scss файлы в один оптимизированный стилевой файл style.css;
- JS — те или иные скрипты, все .js файлы, хотелось бы тоже собрать по всему проекту в один оптимизированный script.js;
- Images — разные статические картинки, которые учавствуют в оформлении. Их будем собирать по всему проекту в одну папку без сохранения изначальной стркутуры папок, а так же оптимизировать размер;
- Live Dev Server — хотелось бы как-то налету применять все изменения при разработке, за это будет отвечать локальный сервер.
Сначала мы рассмотрим отдельные части кода, потом соберем весь пазл.
Необходимые плагины
Плагины мы устанавливаем, как dev зависимости с помощью npm например.
npm i -D gulp browser-sync gulp-flatten del...
Соотвественно начало нашего настроечного файла будет содержать подключение всех установленных плагинов. Их смысл во многом понятен из названий и будет разобран ниже.
// COMMON
import gulp from 'gulp';
const { src, dest, watch, series } = gulp;
import { deleteAsync } from 'del';
import syncServer from 'browser-sync';
const sync = syncServer.create();
import flatten from 'gulp-flatten';
// STYLE
import * as dartSass from 'sass';
import gulpSass from 'gulp-sass';
const sass = gulpSass(dartSass);
import autoprefixer from 'gulp-autoprefixer';
import minify from 'gulp-clean-css';
import sourcemaps from 'gulp-sourcemaps';
import concat from 'gulp-concat';
// HTML
import include from 'gulp-file-include';
// IMAGES
import imagemin from 'gulp-imagemin';
HTML
В HTML нас ждет один из самых приятных сюрпризов, это возможность разделять код на файлы и подключать и в любом месте других файлов, например так:
<head>
@@include('src/components/meta/index.html')
<title>Title</title>
</head>
За работу с html будет отвечать одноименная функция, заметьте, что мы не берем все .html из проекта, а только те, что считаем страницами, при этом шаблоны подключаются из папки компонентов:
function html() {
return src('src/pages/**/**.html') // берем все файлы по шаблону
.pipe(
include({
prefix: '@@',
basepath: '@root',
}),// запускаем плагин, который подставит все темплейты
)
.pipe(dest('dist')); // кладем файлы с сохранением структуры и проект
}
SASS/SCSS
Тут мы будем использовать последовательное включение разных плагинов для потока файлов, большинство названий говорящие, так что особых пояснений не требуется. Если что-то не ясно, можно уточнить по имени плагина.
function scss() {
return src('src/**/**.scss') // берем все файлы с расширением .scss
.pipe(sourcemaps.init()) // начинаем собирать sourcemap информацию
.pipe(autoprefixer()) // добавляем браузерные префиксы
.pipe(sass().on('error', sass.logError)) // препроцессор sass
.pipe(concat('style.min.css')) // собираем все в 1 файл
.pipe(minify()) // минифицируем
.pipe(sourcemaps.write('.')) // указываем sourcemap туже директорию
.pipe(dest('dist/assets/css')); // сохраняем конечный фалй
}
JS
C JS все достаточно просто, собираем в один файл всё с расширением .js. Но Вы можете подключить дополнительные плагины для манификации кода например.
function js() {
return src('src/**/**.js') // выбираем файлы по маске
.pipe(concat('script.js')) // сиединяем в один файл script.js
.pipe(dest('dist/assets/js')); // сохраняем в необходимую директорию
}
Images
Собираем все картинки в папке, и обрабатываем необходимым образом.
function images() {
return src('src/assets/images/*') // выбираем файлы по маске
.pipe(imagemin()) // оптимизируем картинки
.pipe(flatten()) // избавляемся от вложенности, можно убрать
.pipe(dest('dist/assets/images/')); // сохраняем в проект
}
Вспомогательные функции
Еще нам понадобится, как уже упоминалось, сервер и функция очистки проекта. Сервер работает по принципу слежения за соответствующими файлами и запуску функций при их изменении.
function clear() {
return deleteAsync('dist'); // удаляем все файлы из итогового проекта
}
function serve() {
// инициализируем сервер, который хостит нашу папку итогового проекта
sync.init({ server: './dist' });
// следим за файлами по маске и запускаем функции при их изменении
// далее перезагружаем сервер
watch(['src/**/**.html'], series(html)).on('change', sync.reload);
watch(['src/**/**.scss'], series(scss)).on('change', sync.reload);
watch(['src/assets/images/*'], series(images)).on('change', sync.reload);
watch('src/**/**.js', series(js)).on('change', sync.reload);
}
Функции сборки проекта
В итоге для удобства нам хотелось бы иметь короткие функции сборки всего проекта и запуска их из консоли. Нам понадобятся dev и build сборки. Запускать их будем так:
gulp dev
gulp build
Для сборок будем использовать наборы функций, которые запускаются последовательно, для этого используем метод gulp — series. Он возвращает функцию, которую мы экспортируем и сможем использовать для запуска из коммандной строки.
// series последовательно запускает указанные функции
const build = series([clear, scss, html, js, images]);
const dev = series([clear, scss, html, js, images, serve]);
export { build, dev };
Как видно из кода, различием dev сборки только в том, что она запускает тестовый сервер. Но Вы конечно можете кастомизировать порядок и настройки под ваши задачи и вкус.
Итоговый файл настройки
// COMMON
import gulp from 'gulp';
const { src, dest, watch, series } = gulp;
import { deleteAsync } from 'del';
import syncServer from 'browser-sync';
const sync = syncServer.create();
import flatten from 'gulp-flatten';
// STYLE
import * as dartSass from 'sass';
import gulpSass from 'gulp-sass';
const sass = gulpSass(dartSass);
import autoprefixer from 'gulp-autoprefixer';
import minify from 'gulp-clean-css';
import sourcemaps from 'gulp-sourcemaps';
import concat from 'gulp-concat';
// HTML
import include from 'gulp-file-include';
// IMAGES
import imagemin from 'gulp-imagemin';
function html() {
return src('src/pages/**/**.html')
.pipe(
include({
prefix: '@@',
basepath: '@root',
}),
)
.pipe(dest('dist'));
}
function images() {
return src('src/assets/images/*')
.pipe(imagemin())
.pipe(flatten())
.pipe(dest('dist/assets/images/'));
}
function scss() {
return src('src/**/**.scss')
.pipe(sourcemaps.init())
.pipe(autoprefixer())
.pipe(sass().on('error', sass.logError))
.pipe(concat('style.min.css'))
.pipe(minify())
.pipe(sourcemaps.write('.'))
.pipe(dest('dist/assets/css'));
}
function js() {
return src('src/**/**.js').pipe(concat('script.js')).pipe(dest('dist/assets/js'));
}
function clear() {
return deleteAsync('dist');
}
function serve() {
sync.init({ server: './dist' });
watch(['src/**/**.html'], series(html)).on('change', sync.reload);
watch(['src/**/**.scss'], series(scss)).on('change', sync.reload);
watch(['src/assets/images/*'], series(images)).on('change', sync.reload);
watch(['src/**/**.js'], series(js)).on('change', sync.reload);
}
const build = series([clear, scss, html, js, images]);
const dev = series([clear, scss, html, js, images, serve]);
export { build, dev };
Заключение
В этой статье мы описали простейший вариант настройки Gulp, при этом обладающий всеми необходимыми инструментами для сборки и оптимизации проекта. Вы, конечно, всегда можете дополнить его плагинами и настройками на Ваш вкус.
Если остались вопросы, напишите нам на почту, мы постараемся помочь!