Gulp

Матеріал з Wiki.Zina
Версія від 16:50, 6 листопада 2017, створена >WikiSysop (→Ссылки и источники)
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

Настройка сборщика проектов и менеджера задач Gulp в связке с Bower, Sass, Browsersync и Bootstrap.

Установка Gulp в системе

[ред. | ред. код]

Перед установкой 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

Использование Gulp в проекте

[ред. | ред. код]

Перейдите в папку проекта и выполните инициализацию 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 имя-плагина

Задача style — компилирование из Sass в CSS

[ред. | ред. код]

После инициализации 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 отсутствует, поэтому компилировать нечего.

Добавление Bootstrap

[ред. | ред. код]

С помощью 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

Произойдет следующее:

  1. Gulp откроет файл src/scss/style.scss.
  2. Найдет в нем команду импорта @import "bootstrap";.
  3. Поищет файл _bootstrap.scss в доступных ему папках includePaths и найдет его в папке src/scss/.
  4. В файле src/scss/_bootstrap.scss Gulp увидит команды импорта типа @import "bootstrap/variables"; и начнет искать папку bootstrap с файлом _variables.scss внутри.
  5. …и найдет её в папке 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 кб.

Проверка Bootstrap

[ред. | ред. код]

Bootstrap 3

[ред. | ред. код]

Для проверки контроля над стилями cоздайте в дополнение к style.scss файл _variables.scss, в котором будут переопределяться переменные Bootstrap, и тоже импортируйте его:

touch src/scss/_variables.scss
echo '@import "variables";' >> src/scss/style.scss

Добавьте в файл src/scss/_variables.scss строку:

$baseFontSize: 14px;

Bootstrap 4

[ред. | ред. код]

В отличие от 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;

Тестирование в HTML

[ред. | ред. код]

Создайте 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 в браузере.

Задача js — сборка JavaScript

[ред. | ред. код]

Используем плагины:

  • 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

[ред. | ред. код]

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

Задача sprite — сборка CSS спрайтов

[ред. | ред. код]

Используем плагин 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, // Отступ; полезно, чтобы избежать артефактов во время изменения размеров окна браузера
    …
  }));

Задача build — сборка проекта (запуск нескольких задач)

[ред. | ред. код]

Создайте в gulpfile.js задачу build, которая будет запускать несколько задач по сборке:

// Задача: запуск остальных задач
gulp.task('build', [
  'sprite',
  'style',
  'js',
]);

Проверьте:

gulp build

Задача watch — наблюдение за изменениями файлов

[ред. | ред. код]

Для отслеживания изменений файлов и автоматического запуска необходимых задач мы будем использовать плагин 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

Plumber — отслеживание ошибок без прерывания работы Gulp

[ред. | ред. код]

Одна из самых удобных возможностей 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
  …
});

Задача live — автоматическое обновление окна браузера с помощью BrowserSync

[ред. | ред. код]

Установим и настроим плагин 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 по умолчанию

[ред. | ред. код]

Если запустить 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

Обновление Gulp проекта

[ред. | ред. код]
rm -rf node_modules/ bower_components/
npm install
./node_modules/.bin/bower install
./node_modules/.bin/gulp build

Ссылки и источники

[ред. | ред. код]