Gulp
Настройка сборщика проектов и менеджера задач Gulp в связке с Bower, Sass, Browsersync и Bootstrap.
Перед установкой Gulp установите Node.js и NPM:
sudo apt install -y curl
curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
sudo apt install -y nodejs
Установите Bower, Browsersync и Gulp:
sudo npm install --global bower browser-sync gulp-cli
npm rebuild node-sass
Перейдите в папку проекта и выполните инициализацию NPM:
npm init --yes
В папке проекта будет создан файл настроек package.json
Затем инициализируйте Bower:
bower init
На вопросы можно отвечать просто нажатием Enter. Будет создан файл настроек bower.json.
Установите в проекте Gulp:
npm install --save-dev gulp
В папке проекта появится папка node_modules.
Создайте файл gulpfile.js:
touch gulpfile.js
и вставьте в него код:
'use strict';
var gulp = require('gulp');
gulp.task('default', function() {
// place code for your default task here
});
В этом файле gulpfile.js мы будем писать на языке JavaScript задачи — gulp.task.
Теперь можно запустить Gulp:
gulp
— будет выполнена default gulp.task, которая не делает ничего.
Установка плагинов Gulp в проекте делается аналогично установке самого Gulp: npm install --save-dev имя-плагина
При использовании плагинов Gulp учитывайте официальный черный список плагинов, чтобы не использовать дублирующиеся и неподдерживаемые плагины.
Важно: в случае обновления Gulp, возможно, потребуется пересборка плагинов: npm rebuild имя-плагина
После инициализации Bower и Gulp в папке проекта будет создана следующая файловая структура:
node_modules/ bower.json package.json
Если выполнить установку с помощью Bower какой-то библиотеки, например, jQuery: bower install --save-dev jquery, то в корне проекта появится папка bower_components, содержащая соответствующие библиотеки.
Созайте папку для хранения рабочих файлов src, и внутри нее папки для Sass, спрайтов и JavaScript:
mkdir src src/scss src/sprite src/js
Теперь добавьте в gulpfile.js переменную path, в которой пропишите все используемые пути. Это пригодится, если вы решите поменять имена или вложенность папок — например, сгруппировать всё в папку themes/my_theme.
var path = {
src: { // Где брать исходники
style: './src/scss/style.scss',
sprite: './src/sprite/*.png',
js: './src/js/main.js',
},
build: { // Куда складывать после сборки готовые файлы
style: './html/css/',
sprite: './html/img/',
js: './html/js/',
}
};
Синтаксис шаблонов путей:
sprite/*.png— взять все файлы с расширением.pngв папкеsprite.img/**/*.*— взять все файлы всех расширений из папкиimgи из вложенных папок.
Далее используем плагины Gulp:
gulp-sass— компилирование из Sass в CSS с помощью LibSass — написанного на С/C++ компилятора (и поэтому он работает очень быстро). Официальная инструкция.gulp-autoprefixer— автоматическое добавление к CSS свойствам вендорных префиксов, основанных на последних спецификациях. По умолчанию ставит префиксы, необходимые для двух последних версий браузеров. Настройки.
Замечание. Одна из типичных задач Gulp — минификация (сжатие) CSS кода. Раньше для этого использовался плагин gulp-minify-css, но сейчас его авторы предлагают использовать gulp-cssnano. В этом руководстве мы вообще обходимся без плагинов минификации и используем параметр outputStyle: 'compressed' основного плагина gulp-sass.
Установите плагины gulp-sass и gulp-autoprefixer:
npm install --save-dev gulp-sass gulp-autoprefixer
Добавьте в файл gulpfile.js список установленных плагинов и задачу style:
var sass = require('gulp-sass');
var prefixer = require('gulp-autoprefixer');
// Задача: компилирование Sass в CSS
gulp.task('style', function () {
gulp.src(path.src.style) // Возьмем наш основной Sass файл 'style.scss'
.pipe(sass({ // Скомпилируем Sass в CSS
outputStyle: 'compressed', // Минифицируем CSS
}))
.pipe(prefixer({ // Добавим вендорные префиксы
browsers: [
'last 2 versions',
'> 1%'
]
}))
.pipe(gulp.dest(path.build.style)) // Положим готовый 'style.css' в build
});
Выполните задачу:
gulp style
Впрочем, пока что src/scss/style.scss отсутствует, поэтому компилировать нечего.
С помощью Bower установите Sass версию Bootstrap:
- Bootstrap 3:
bower install --save-dev bootstrap-sass
- Bootstrap 4:
bower install --save-dev bootstrap#v4.0.0-alpha.6
Актуальную версию Bootstrap 4 уточните здесь: http://v4-alpha.getbootstrap.com/getting-started/download/#bower
Bootstrap будет установлен в папку bower_components. Заодно туда же будет установлен jQuery, потому что он требуется для Bootstrap.
Скопируйте в свою рабочую папку с Sass стилями файл _bootstrap.scss:
- Bootstrap 3:
cp bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss src/scss/
- Bootstrap 4:
cp bower_components/bootstrap/scss/bootstrap.scss src/scss/_bootstrap.scss
Добавьте в файл src/scss/style.scss команду импорта файла _bootstrap.scss:
echo '@import "bootstrap";' >> src/scss/style.scss
Добавьте в файл gulpfile.js в задачу style (компилирование Sass в CSS) пути к папкам, в которых Gulp будет искать стили Bootstrap:
.pipe(sass({ // Скомпилируем Sass в CSS
includePaths: [ // Включим папки для поиска файлов Bootstrap
'./src/scss/',
'./bower_components/bootstrap-sass/assets/stylesheets/', // Bootstrap 3
// './bower_components/bootstrap/scss/', // Bootstrap 4
],
outputStyle: 'compressed', // Минифицируем CSS
}))
Выполните команду:
gulp style
Произойдет следующее:
- Gulp откроет файл src/scss/style.scss.
- Найдет в нем команду импорта @import "bootstrap";.
- Поищет файл _bootstrap.scss в доступных ему папках includePaths и найдет его в папке src/scss/.
- В файле src/scss/_bootstrap.scss Gulp увидит команды импорта типа @import "bootstrap/variables"; и начнет искать папку bootstrap с файлом _variables.scss внутри.
- …и найдет её в папке bower_components/bootstrap-sass/assets/stylesheets/.
Будет создан CSS файл, готовый для подключения в HTML, минифицированный и с вендорными префиксами: html/css/style.css
Теперь вы можете регулировать, какой объем возможностей Bootstrap вы будете использовать в своем проекте, просто отключая и включая (комментируя двумя слэшами //) команды импорта отельных составляющих Bootstrap в файле src/scss/_bootstrap.scss.
Например, минимальный набор компонентов Bootstrap, чтобы можно было использовать его сетку:
// Core variables and mixins
@import "bootstrap/variables";
@import "bootstrap/mixins";
// Reset and dependencies
@import "bootstrap/normalize";
// Core CSS
@import "bootstrap/grid";
В этом случае размер готового файла style.css получится:
- Bootstrap 3: в несжатом виде 13 кб, в минифицированном (с включенной опцией
outputStyle: 'compressed') — 10 кб. - Bootstrap 4: в несжатом виде 18 кб, в минифицированном — 13 кб.
Для проверки контроля над стилями cоздайте в дополнение к style.scss файл _variables.scss, в котором будут переопределяться переменные Bootstrap, и тоже импортируйте его:
touch src/scss/_variables.scss
echo '@import "variables";' >> src/scss/style.scss
Добавьте в файл src/scss/_variables.scss строку:
$baseFontSize: 14px;
В отличие от 3-й версии, в Bootstrap 4 есть специальный пустой файл _custom.scss, предназначенный для переопределения переменных. Весь список переменных с их стандартными значениями можно смотреть в файле _variables.scss. Для удобства скопирум оба файла в папку проекта, но редактировать будем только _custom.scss — точнее, будем копировать в него нужные переменные из файла _variables.scss и менять их значения.
cp bower_components/bootstrap/scss/_custom.scss src/scss/_custom.scss
cp bower_components/bootstrap/scss/_variables.scss src/scss/_variables.scss
Как-то специально импортировать _custom.scss в style.scss не нужно — он и так подключается в src/scss/_bootstrap.scss.
Добавьте в файл src/scss/_custom.scss строку:
$font-size-root: 16px;
Создайте index.html и подключите в него style.css, который генерирует Gulp:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Gulp с Bootstrap</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<h1>Заголовок H1</h1>
<p>Абзац текста.</p>
<h2>Заголовок H2</h2>
<p>Второй абзац текста.</p>
<h3>Заголовок H3</h3>
<p>Третий абзац текста.</p>
</body>
</html>
Теперь измените размер базового шрифта:
- Bootstrap 3:
$baseFontSizeв файлеsrc/scss/_variables.scss - Bootstrap 4:
$font-size-baseв файлеsrc/scss/_custom.scss
Обновите css/style.css командой gulp style и проверьте, как меняется вид index.html в браузере.
Используем плагины:
gulp-uglify— сжатие JavaScript кода.gulp-rigger— для импорта содержимого одних файлов в другие простой конструкцией вида//= another_file.js
Установите эти плагины:
npm install --save-dev gulp-uglify gulp-rigger
Добавьте в gulpfile.js:
var uglify = require('gulp-uglify');
var rigger = require('gulp-rigger');
// Задача: сборка JavaScript файлов
gulp.task('js', function () {
gulp.src(path.src.js) // Возьмем наш основной файл 'main.js'
.pipe(rigger()) // Включим в него все импортируемые файлы
.pipe(uglify()) // Сожмем полученный JS
.pipe(gulp.dest(path.build.js)) // Положим готовый 'main.js' в build
});
Создайте в папке src/js файл main.js:
touch src/js/main.js
В этом файле пропишите список JavaScript файлов, которые будут импортироваться в него посредством плагина gulp-rigger:
/*
* Third party
*/
//= ../../bower_components/jquery/dist/jquery.js
Выполнить задачу:
gulp js
Gulp создаст минифицированный файл main.js в папке html/js/
Чтобы подключить другие файлы, например, файл src/js/partials/app.js, нужно сначала создать такой файл, а затем подключить его в основном файле src/js/main.js аналогичным образом:
/*
* Custom
*/
//= partials/app.js
SourceMaps используются, чтобы читать и отлаживать минифицированный CSS и JavaScript. Подробнее.
Для этого установите плагин gulp-sourcemaps:
npm install --save-dev gulp-sourcemaps
Добавьте в начало файла gulpfile.js:
var sourcemaps = require('gulp-sourcemaps');
Добавьте две строки:
.pipe(sourcemaps.init()) // Инициализируем SourceMap.pipe(sourcemaps.write()) // Добавим SourceMap
в задачу style:
// Задача: компилирование Sass в CSS
gulp.task('style', function () {
gulp.src(path.src.style) // Возьмем наш основной Sass файл 'style.scss'
.pipe(sourcemaps.init()) // Инициализируем SourceMap
.pipe(sass({ // Скомпилируем Sass в CSS
outputStyle: 'compressed',
}))
.pipe(prefixer({ // Добавим вендорные префиксы
browsers: [
'last 2 versions',
'> 1%'
]
}))
.pipe(sourcemaps.write()) // Добавим SourceMap
.pipe(gulp.dest(path.build.style)) // Положим готовый 'style.css' в build
});
и в задачу js:
// Задача: сборка JavaScript файлов
gulp.task('js', function () {
...
.pipe(sourcemaps.init()) // Инициализируем SourceMap
.pipe(uglify()) // Сожмем полученный JS
.pipe(sourcemaps.write()) // Добавим SourceMap
...
});
Проверьте двумя командами:
gulp style gulp js
Используем плагин Gulp gulp.spritesmith.
Замечание. Существуют как минимум три плагина Gulp для сборки CSS спрайтов на основе spritesmith: gulp-sprite-generator, gulp-spritesmith, gulp.spritesmith. Мы будем использовать последний — gulp.spritesmith — потому что это официальный порт для Gulp grunt-spritesmith, Grunt-враппера spritesmith.
Установите плагин gulp.spritesmith:
npm install --save-dev gulp.spritesmith
Добавьте в gulpfile.js:
var spritesmith = require('gulp.spritesmith');
// Задача: сборка CSS спрайтов
gulp.task('sprite', function () {
var spriteData = gulp.src('src/sprite/*.png')
.pipe(spritesmith({
imgName: 'sprite.png',
cssName: 'sprite.css'
}));
spriteData.img.pipe(gulp.dest('img'));
spriteData.css.pipe(gulp.dest('css'));
});
Положите отдельные .png файлы спрайтов в папку src/sprite/ и запустите:
gulp sprite
В результате в папке img появится файл sprite.png с собранными в одну картинку спрайтами, а в папке css появится файл sprite.css, в котором будет написан CSS код для использования этих спрайтов.
Варианты тонкой настройки gulp.spritesmith (подробнее см. https://github.com/twolfson/gulp.spritesmith):
.pipe(spritesmith({
algorithm: 'top-down', // Выстраивать изображения в столбик
padding: 2, // Отступ; полезно, чтобы избежать артефактов во время изменения размеров окна браузера
…
}));
Создайте в gulpfile.js задачу build, которая будет запускать несколько задач по сборке:
// Задача: запуск остальных задач
gulp.task('build', [
'sprite',
'style',
'js',
]);
Проверьте:
gulp build
Для отслеживания изменений файлов и автоматического запуска необходимых задач мы будем использовать плагин gulp-watch.
В Gulp есть встроенный watch, но он не всегда работает так, как нужно.
Установите плагин gulp-watch:
npm install --save-dev --no-optional chokidar gulp-watch
Добавьте в gulpfile.js:
var watch = require('gulp-watch');
var path = {
…
watch: { // За изменением каких файлов будем наблюдать
style: './src/scss/**/*.scss',
sprite: './src/sprite/**/*.png',
js: './src/js/**/*.js',
}
};
// Задача: отслеживание изменений файлов и запуск соответствующих задач
gulp.task('watch', function(){
watch([path.watch.style], function(event, cb) {
gulp.start('style');
});
watch([path.watch.js], function(event, cb) {
gulp.start('js');
});
watch([path.watch.sprite], function(event, cb) {
gulp.start('sprite');
});
});
Теперь достаточно перейти в консоли в папку проекта и запустить:
gulp watch
После чего Gulp начнет отслеживание файлов в src/ и, по мере появления изменений в этих файлах, будет перекомпилировать соответствующие файлы в папки, указанные в переменной path.build.
Прервать работу watch можно стандартным сочетанием клавиш для команд, запущенных в терминале: Ctrl+C
Одна из самых удобных возможностей Gulp — автоматическая обработка измененных файлов через gulp.watch.
Однако, если вы допустите в коде отслеживаемых файлов ошибку или опечатку, то gulp.watch будет прерван и Gulp выдаст сообщение об ошибке. Причем даже в этом случае довольно трудно разобраться, где именно ошибка.
Плагин gulp-plumber формирует вывод об ошибке и при этом работа Gulp не прерывается.
Установите плагин gulp-plumber:
npm install --save-dev --no-optional gulp-plumber
Добавьте в gulpfile.js зависимость:
var plumber = require('gulp-plumber');
Теперь добавьте строку .pipe(plumber()) в те задачи, в которых необходимо включить возможность отслеживания ошибок.
// Задача: компилирование Sass в CSS
gulp.task('style', function () {
gulp.src(path.src.style) // Возьмем наш основной Sass файл 'style.scss'
.pipe(plumber()) // Включим отслеживание ошибок
.pipe(sourcemaps.init()) // Инициализируем SourceMap
…
});
Установим и настроим плагин browser-sync — dev-сервер для автоматического обновления окна браузера при измененийй файлов сайта.
Установите browser-sync:
npm install --save-dev --no-optional browser-sync
Добавьте в gulpfile.js:
var browserSync = require('browser-sync').create();
var reload = browserSync.reload;
// Задача: автоматическое обновление окна браузера с помощью BrowserSync
gulp.task('live', function () {
browserSync.init({
proxy: "example.dev"
// server: {
// baseDir: "./html/"
// }
});
gulp.watch([path.watch.html]).on("change", reload);
});
Протестируйте:
gulp live
Откроется окно браузера с сайтом по адресу http://localhost:3000/. Внесите изменения в файл html/index.html и увидите, как они сразу отобразятся в окне браузера.
По адресу http://localhost:3001 доступен веб-интерфейс к BrowserSync.
Прервать работу BrowserSync: Ctrl+C
Если запустить gulp без параметров, то он попытается выполнить задачу с именем default. И если в gulpfile.js нет такой задачи, вы получите сообщение об ошибке.
Создайте в gulpfile.js эту задачу и добавьте в нее те задачи, которые вы хотите, чтобы Gulp выполнял по умолчанию.
Например:
build— сборка проекта,live— запуск сервера BrowserSync,watch— запуск наблюдения за папкой с рабочими файлами.
// Default task
gulp.task('default', [
'build',
'live',
'watch'
]);
Установите Gulp в системе:
curl -sL https://deb.nodesource.com/setup_5.x | sudo -E bash - sudo apt install -y nodejs sudo npm install --global bower browser-sync gulp-cli
Инициализируйте:
npm init --yes bower init
Установите Gulp и его плагины:
npm install --save-dev gulp gulp-sass gulp-autoprefixer gulp-uglify gulp-rigger gulp-sourcemaps gulp.spritesmith npm install --save-dev --no-optional chokidar gulp-watch gulp-plumber browser-sync
Создайте папки для исходного кода:
mkdir src src/scss src/sprite src/js
Установите Bootstrap:
— Bootstrap 3:
bower install --save-dev bootstrap-sass
cp bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss src/scss/
echo '@import "bootstrap";' >> src/scss/style.scss
— Bootstrap 4:
bower install --save-dev bootstrap#v4.0.0-alpha.5
cp bower_components/bootstrap/scss/bootstrap.scss src/scss/_bootstrap.scss
cp bower_components/bootstrap/scss/_custom.scss src/scss/
cp bower_components/bootstrap/scss/_variables.scss src/scss/
echo '@import "bootstrap";' >> src/scss/style.scss
Добавьте в src/js/main.js:
touch src/js/main.js
/*
* Third party
*/
//= ../../bower_components/jquery/dist/jquery.js
Добавьте следующий код в gulpfile.js:
touch gulpfile.js
'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var prefixer = require('gulp-autoprefixer');
var uglify = require('gulp-uglify');
var rigger = require('gulp-rigger');
var sourcemaps = require('gulp-sourcemaps');
var spritesmith = require('gulp.spritesmith');
var watch = require('gulp-watch');
var plumber = require('gulp-plumber');
var browserSync = require('browser-sync').create();
var reload = browserSync.reload;
var path = {
src: { // Где брать исходники
style: './src/scss/style.scss',
sprite: './src/sprite/*.png',
js: './src/js/main.js',
},
build: { // Куда складывать после сборки готовые файлы
style: './html/css/',
sprite: './html/img/',
js: './html/js/',
},
watch: { // За изменением каких файлов будем наблюдать
html: './html/**/*.html',
style: './src/scss/**/*.scss',
build_style: './html/css/*.css',
js: './src/js/**/*.js',
build_js: './html/js/**/*.js',
sprite: './src/sprite/**/*.png',
}
};
// Задача: компилирование Sass в CSS
gulp.task('style', function () {
gulp.src(path.src.style) // Возьмем наш основной Sass файл 'style.scss'
.pipe(sourcemaps.init()) // Инициализируем SourceMap
.pipe(sass({ // Скомпилируем Sass в CSS
includePaths: [ // Включим папки для поиска файлов Bootstrap
'./src/scss/',
'./bower_components/bootstrap-sass/assets/stylesheets/', // Bootstrap 3
// './bower_components/bootstrap/scss/', // Bootstrap 4
],
outputStyle: 'compressed', // Минифицируем CSS
}))
.pipe(prefixer({ // Добавим вендорные префиксы
browsers: [
'last 2 versions',
'> 1%'
]
}))
.pipe(sourcemaps.write()) // Добавим SourceMap
.pipe(gulp.dest(path.build.style)) // Положим готовый 'style.css' в build
});
// Задача: сборка JavaScript файлов
gulp.task('js', function () {
gulp.src(path.src.js) // Возьмем наш основной файл 'main.js'
.pipe(rigger()) // Включим в него все импортируемые файлы
.pipe(sourcemaps.init()) // Инициализируем SourceMap
.pipe(uglify()) // Сожмем полученный JS
.pipe(sourcemaps.write()) // Добавим SourceMap
.pipe(gulp.dest(path.build.js)) // Положим готовый 'main.js' в build
});
// Задача: сборка CSS спрайтов
gulp.task('sprite', function () {
var spriteData = gulp.src(path.src.sprite)
.pipe(spritesmith({
imgName: 'sprite.png',
cssName: 'sprite.css'
}));
spriteData.img.pipe(gulp.dest(path.build.sprite));
spriteData.css.pipe(gulp.dest(path.build.style));
});
// Задача: сборка проекта (запуск нескольких задач)
gulp.task('build', ['sprite', 'style', 'js',]);
// Задача: отслеживание изменений файлов и запуск соответствующих задач
gulp.task('watch', function() {
watch([path.watch.style], function(event, cb) {
gulp.start('style');
});
watch([path.watch.js], function(event, cb) {
gulp.start('js');
});
watch([path.watch.sprite], function(event, cb) {
gulp.start('sprite');
});
});
// Задача: автоматическое обновление окна браузера с помощью BrowserSync
gulp.task('live', function () {
browserSync.init({
// proxy: "example.dev"
server: {
baseDir: "./html/"
}
});
gulp.watch([path.watch.html]).on("change", reload);
gulp.watch([path.watch.build_style]).on("change", reload);
gulp.watch([path.watch.build_js]).on("change", reload);
});
// Задача по умолчанию
gulp.task('default', ['build', 'live', 'watch']);
Теперь достаточно перейти в терминале в папку проекта и запустить в ней команду:
gulp
rm -rf node_modules/ bower_components/
npm install
./node_modules/.bin/bower install
./node_modules/.bin/gulp build
- Gulp и Drupal
- Hugo + Gulp
- gulp/getting-started.md at master — официальная инструкция по установке Gulp
- Приятная сборка frontend проекта / Хабрахабр
- Синхронная обработка задач в Gulp.JS | Frontender Magazine — о последовательности и одновременности запуска задач Gulp
- Основной источник про связку Gulp и Drupal: Drupal 101: Theming Drupal 7 with gulp
- Быстрая разработка на 1С-Битрикс или как я познакомился с gulp / Хабрахабр
- Пример конфига Gulp
- Простое и удобное gulp‑окружение для разработки html5‑игры меньше, чем за 5 минут | Frontender Magazine