Кратко
СкопированоGulp (англ. «глоток» [/gʌlp/, /галп/]) — менеджер для организации и выполнения задач при разработке приложений с использованием платформы Node.js.
Gulp может выполнять разные задачи: формировать файлы стилей, объединять и минифицировать файлы, оптимизировать изображения, транспилировать код и т. д. При выполнении этих задач происходит взаимодействие с рабочим окружением: обратиться к файловой системе, создать или сохранить итоговый файл, запустить процесс локального web-сервера, показать результат в браузере.
Как понять
СкопированоGulp — это менеджер задач. Он выполняет объявленные инструкции в указанной последовательности. Gulp не предоставляет разработчику готовые механизмы для сборки проекта, но позволяет настроить такую сборку с помощью необходимых модулей.
Часто в своих проектах разработчики используют Webpack, но это — сборщик модулей для приложений, написанных на JavaScript. Он «из коробки» предлагает решения для сборки проектов с использованием уже подготовленных механизмов и настроек. Подробнее об этом инструменте читайте в нашей статье про Webpack.
Модули и задачи
СкопированоПри работе с web-проектом разработчику необходимо выполнять ряд повторяющихся операций:
- проверять HTML-разметку и CSS-правила;
- преобразовывать синтаксис CSS-препроцессоров в «чистый» CSS;
- проверять JS-код на соответствие требуемым стандартам;
- при необходимости объединять несколько файлов (CSS или JS) в один;
- минифицировать большие файлы;
- проверять в браузере результат, желательно по принципу «live-reload» («живая перезагрузка»);
- формировать итоговую сборку проекта.
С использованием Gulp, выполнение всех этих задач можно организовать с применением специальных модулей, которые распространяются средствами пакетных менеджеров.
Все инструкции по организации работы проекта указываются в файле gulpfile.js. Сначала объявляются основные свойства, которые Gulp использует при выполнении задач:
const { src, dest, parallel, series, watch } = require('gulp')
const { src, dest, parallel, series, watch } = require('gulp')
srcвыполняет чтение исходных файлов;( ) destвыполняет запись итоговых файлов;( ) parallelобъединяет задачи для выполнения в параллельном режиме;( ) seriesобъединяет задачи для выполнения в последовательном режиме;( ) watchзапускает необходимые задачи при изменениях в файлах.( )
Потом таким же способом подключаются необходимые npm-модули, например:
const sass = require('gulp-sass')(require('sass'))const browserSync = require('browser-sync').create()const autoprefixer = require('gulp-autoprefixer')
const sass = require('gulp-sass')(require('sass'))
const browserSync = require('browser-sync').create()
const autoprefixer = require('gulp-autoprefixer')
Затем создаются рабочие задачи со следующей структурой:
- указывается расположение исходных файлов;
- с использованием оператора
pipeвыстраивается последовательность выполнения операций;( ) - определяется место, куда будут сохраняться итоговые файлы.
Чтобы к такой задаче можно было обратиться в любом месте gulpfile.js, ей обязательно присваивается своё название.
Задача — task
СкопированоПодготовим инструкцию для обработки файла стилей, созданных с использованием CSS-препроцессора SASS, для которой установим следующую последовательность действий:
- обратиться к исходному файлу в папке
/src;/ styles / - преобразовать синтаксис SASS в стандартный CSS;
- вывести в терминале информацию о наличии ошибок в исходном файле;
- сохранить итоговый файл в папку
/public;/ styles / - применить с помощью модуля
browserновые стили для открытой в браузере страницы.- sync
До третьей версии Gulp задачи создавались встроенной функцией gulp:
gulp.task('styles', function() { return src('./src/styles/style.scss') .pipe(sass().on('error', sass.logError)) .pipe(dest('./public/styles/style.css')) .pipe(browserSync.stream())})
gulp.task('styles', function() {
return src('./src/styles/style.scss')
.pipe(sass().on('error', sass.logError))
.pipe(dest('./public/styles/style.css'))
.pipe(browserSync.stream())
})
Эта функция регистрирует объявленную инструкцию в качестве общедоступной задачи с названием styles, которая может взаимодействовать с рабочим окружением. Теперь такую задачу можно запускать на выполнение как отдельно — командой gulp styles, так и в составе сводной задачи (watch, default и т. п.).
Задача — function
СкопированоНачиная с четвёртой версии Gulp, для создания задач рекомендуется использовать обычные функции. В этом случае задача из примера выше будет выглядеть следующим образом:
function styles() { return src('./src/styles/style.scss') .pipe(sass().on('error', sass.logError)) .pipe(dest('./public/styles/style.css')) .pipe(browserSync.stream())}
function styles() {
return src('./src/styles/style.scss')
.pipe(sass().on('error', sass.logError))
.pipe(dest('./public/styles/style.css'))
.pipe(browserSync.stream())
}
Формирование задачи с использованием такой функции создаёт инструкцию, которая доступна только для внутреннего использования. Чтобы объявленная функция могла взаимодействовать с рабочим окружением и выполняться командой gulp, её необходимо экспортировать в общедоступную задачу:
exports.styles = styles
exports.styles = styles
Только после этого функция станет доступной для запуска и выполнения как отдельной командой gulp styles, так и в составе сводной задачи.
Отслеживание изменений в проекте
СкопированоПри работе над проектом разработчику необходимо видеть результат изменений, которые он вносит в файлы. Для этой цели в Gulp предусмотрен метод watch, который проверяет файлы при их сохранении и запускает соответствующие задачи.
Для рассмотренных выше примеров задача отслеживания изменений в файлах стилей будет выглядеть так:
- указывается расположение файлов, которые должны отслеживаться;
- вызывается задача
stylesдля обработки этих файлов; - при сохранении изменений выполняется перезагрузка открытой в браузере страницы.
function watch_dev() { watch('./src/styles/style.css', styles).on( 'change', browserSync.reload )}
function watch_dev() {
watch('./src/styles/style.css', styles).on(
'change',
browserSync.reload
)
}
Работа с проектом и его сборка
СкопированоЗапуск проекта в режиме разработки осуществляется сводной задачей default, название которой зарезервировано в Gulp. В примере ниже она будет выполнять и отслеживать в параллельном режиме задачи, ранее экспортированные из функций:
exports.default = parallel( styles, scripts, pages, watch_dev)
exports.default = parallel(
styles,
scripts,
pages,
watch_dev
)
Поскольку задача default для Gulp является задачей по умолчанию, запустить её можно командой gulp.

default задачи в платформе ДокиДля сборки проекта обычно создаётся отдельная задача с произвольным названием, которая последовательно выполняет необходимые действия:
exports.build = series( styles, scripts, pages)
exports.build = series(
styles,
scripts,
pages
)
После этого сборка итоговой версии проекта осуществляется вводом в терминале команды gulp build.
Использование
СкопированоРассмотрим вариант проекта по разработке сайта.
Структура проекта будет организована с использованием компонентного подхода: для каждого блока страницы выделяется отдельная папка. В папке компонента будут располагаться его файлы стилей, разметки и скриптов. В отдельных папках будут храниться изображения и файлы шрифтов.
Все исходные файлы размещаются в папке src, результат будет сохраняться в папку public:
. ├─ /public │ ├─ /css │ ├─ /images │ ├─ /js │ ├─ index.html │ └─ order.html ├─ /src │ ├─ /components │ │ ├─ /header │ │ │ ├─ header.html │ │ │ └─ header.scss │ │ ├─ /offer │ │ │ ├─ offer.html │ │ │ ├─ offer.js │ │ │ └─ offer.scss │ │ ├─ /order │ │ │ ├─ order.html │ │ │ ├─ order.js │ │ │ ├─ order.scss │ │ └─ /footer │ │ ├─ footer.html │ │ ├─ footer.js │ │ └─ footer.scss │ ├─ /fonts │ ├─ /images │ ├─ /js │ │ └─ script.js │ ├─ /pages │ │ ├─ index.html │ │ └─ order.html │ └─ /styles │ └─ style.scss ├─ gulpfile.js └─ package.json
Сначала в рабочей папке командой npm init необходимо выполнить инициализацию проекта, в процессе которой будет предложено указать его данные:

После этого в папке будет создан файл манифеста проекта package.json, в котором также будет сохраняться информация об используемых модулях. Модули устанавливаются стандартной командой npm install.
Нам понадобятся следующие npm-модули:
delдля очистки папкиpublic;sassиgulpдля использования препроцессора SASS;- sass gulpдобавляет необходимые вендорные префиксы CSS;- autoprefixer gulpгруппирует все media-запросы CSS в одном месте итогового файла стилей;- group - css - media - queries gulpподключает отдельные файлы компонентов в итоговые файлы HTML и JS;- include browserсоздаёт и запускает локальный веб-сервер.- sync
В gulpfile.js сначала объявим все необходимые свойства и модули:
const { src, dest, parallel, series, watch } = require('gulp')const del = require('del')const sass = require('gulp-sass')(require('sass'))const autoprefixer = require('gulp-autoprefixer')const gcssmq = require('gulp-group-css-media-queries')const includeFiles = require('gulp-include')const browserSync = require('browser-sync').create()
const { src, dest, parallel, series, watch } = require('gulp')
const del = require('del')
const sass = require('gulp-sass')(require('sass'))
const autoprefixer = require('gulp-autoprefixer')
const gcssmq = require('gulp-group-css-media-queries')
const includeFiles = require('gulp-include')
const browserSync = require('browser-sync').create()
Подготовим задачу для создания модулем browser веб-сервера с использованием свойств API Browsersync:
- инициализируем веб-сервер;
- указываем рабочую папку;
- упрощаем ввод в браузере адреса страницы — без расширения
.html; - назначаем номер порта для взаимодействия с веб-сервером;
- назначаем номер порта для пользовательского интерфейса веб-сервера;
- открываем в браузере главную страницу сайта.
function browsersync() { browserSync.init({ server: { baseDir: './public/', serveStaticOptions: { extensions: ['html'], }, }, port: 8080, ui: { port: 8081 }, open: true, })}
function browsersync() {
browserSync.init({
server: {
baseDir: './public/',
serveStaticOptions: {
extensions: ['html'],
},
},
port: 8080,
ui: { port: 8081 },
open: true,
})
}
Задача по формированию CSS-стилей выполняет следующие операции:
- обращается к исходному файлу
style;. scss - переводит синтаксис SASS в стандартный CSS;
- показывает в терминале информацию о наличии ошибок в исходном файле;
- с использованием Autoprefixer добавляет вендорные префиксы CSS, в т.ч. для работы Grid Layout в браузере IE;
- группирует вместе все медиавыражения и размещает их в конце файла;
- сохраняет итоговый файл в папку
/public;/ css / - с помощью модуля
browserприменяет новые стили для открытой в браузере страницы.- sync
function styles() { return src('./src/styles/style.scss') .pipe(sass().on('error', sass.logError)) .pipe(autoprefixer({ grid: true })) .pipe(gcssmq()) .pipe(dest('./public/css/')) .pipe(browserSync.stream())}
function styles() {
return src('./src/styles/style.scss')
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer({ grid: true }))
.pipe(gcssmq())
.pipe(dest('./public/css/'))
.pipe(browserSync.stream())
}
Для формирования файлов скриптов создадим задачу, в которой укажем следующую последовательность действий:
- обратиться к исходному файлу
script;. js - обработать JS-файлы компонентов;
- применить изменения для открытой в браузере страницы.
function scripts() { return src('./src/js/script.js') .pipe( includeFiles({ includePaths: './src/components/**/', }) ) .pipe(dest('./public/js/')) .pipe(browserSync.stream())}
function scripts() {
return src('./src/js/script.js')
.pipe(
includeFiles({
includePaths: './src/components/**/',
})
)
.pipe(dest('./public/js/'))
.pipe(browserSync.stream())
}
Использование параметра include для модуля gulp позволяет подключать в script.js файлы компонентов без указания полного пути к ним:
//=include offer.js//=include order.js
//=include offer.js
//=include order.js
Этот параметр будет использоваться и при обработке страниц, в результате чего таким же образом в HTML-файлах можно будет использовать файлы компонентов:
<!--=include header.html --><!--=include offer.html --><!--=include order.html --><!--=include footer.html -->
<!--=include header.html -->
<!--=include offer.html -->
<!--=include order.html -->
<!--=include footer.html -->
Страницы сайта будут обрабатываться задачей pages в следующей последовательности:
- считывается исходный файл страницы;
- обрабатываются HTML-файлы компонентов;
- после сохранения изменений выполняется перезагрузка открытой в браузере страницы.
function pages() { return src('./src/pages/*.html') .pipe( includeFiles({ includePaths: './src/components/**/', }) ) .pipe(dest('./public/')) .pipe(browserSync.reload({ stream: true, }))}
function pages() {
return src('./src/pages/*.html')
.pipe(
includeFiles({
includePaths: './src/components/**/',
})
)
.pipe(dest('./public/'))
.pipe(browserSync.reload({ stream: true, }))
}
Для использования шрифтов и картинок создадим задачи, которые в асинхронном режиме будут копировать файлы из папки src в папку public:
function copyFonts() { return src('./src/fonts/**/*') .pipe(dest('./public/fonts/'))}function copyImages() { return src('./src/images/**/*') .pipe(dest('./public/images/'))}async function copyResources() { copyFonts() copyImages()}
function copyFonts() {
return src('./src/fonts/**/*')
.pipe(dest('./public/fonts/'))
}
function copyImages() {
return src('./src/images/**/*')
.pipe(dest('./public/images/'))
}
async function copyResources() {
copyFonts()
copyImages()
}
Перед запуском проекта в режиме разработки, а также перед его сборкой, желательно удалить папку public c предыдущими версиями файлов, поэтому добавим задачу очистки:
async function clean() { return del.sync('./public/', { force: true })}
async function clean() {
return del.sync('./public/', { force: true })
}
Осталось создать задачу, которая для отслеживания изменений в файлах будет выполнять следующие действия:
- следить за файлами, расположенными в указанных папках;
- запускать задачи для обработки указанных файлов;
- перезагружать открытую страницу после сохранения изменений.
function watch_dev() { watch(['./src/js/script.js', './src/components/**/*.js'], scripts) watch(['./src/styles/style.scss', './src/components/**/*.scss'], styles).on( 'change', browserSync.reload ) watch(['./src/pages/*.html', './src/components/**/*.html'], pages).on( 'change', browserSync.reload )}
function watch_dev() {
watch(['./src/js/script.js', './src/components/**/*.js'], scripts)
watch(['./src/styles/style.scss', './src/components/**/*.scss'], styles).on(
'change',
browserSync.reload
)
watch(['./src/pages/*.html', './src/components/**/*.html'], pages).on(
'change',
browserSync.reload
)
}
В конце gulpfile.js экспортируем объявленные функции в общедоступные задачи, после чего создадим сводные задачи для запуска проекта в режиме разработки и сборки его итоговой версии:
exports.browsersync = browsersyncexports.clean = cleanexports.scripts = scriptsexports.styles = stylesexports.pages = pagesexports.copyResources = copyResourcesexports.default = parallel( clean, styles, scripts, copyResources, pages, browsersync, watch_dev)exports.build = series( clean, styles, scripts, copyResources, pages)
exports.browsersync = browsersync
exports.clean = clean
exports.scripts = scripts
exports.styles = styles
exports.pages = pages
exports.copyResources = copyResources
exports.default = parallel(
clean,
styles,
scripts,
copyResources,
pages,
browsersync,
watch_dev
)
exports.build = series(
clean,
styles,
scripts,
copyResources,
pages
)
Заключение
СкопированоЕсли вы работаете над web-проектом, который:
- не основан на современных JS-фреймворках;
- не является SPA или PWA.
Gulp — ваш бро, не сомневайтесь.