Bootstrap 4 - Сборка проекта с помощью Gulp

Александр Мальцев
53K
149
8
Bootstrap 4 - Сборка проекта с помощью Gulp
Содержание:
  1. Инструкция по установке Gulp окружения
  2. Как использовать Gulp окружение?
  3. Описание Gulp окружения
  4. Комментарии

В этой статье рассмотрим пример Gulp окружения, которое можно использовать для комфортной фронтенд разработки веб-проекта. Данный пример по умолчанию сконфигурирован для создания сайтов и веб-приложений, в основу которых положен фреймворк Bootstrap 4.

Проект, рассматриваемый в рамках этой статьи расположен на Github по адресу: https://github.com/itchief/gulp-project-bootstrap-4

Видео к этой статье:

Инструкция по установке Gulp окружения

Для создания окружения необходимо иметь следующие установленные программы:

  • "Node.js" (загрузить установщик "Node.js" для своей операционной системы можно c этой страницы; для проекта требуется версия программы не ниже 10);
  • "Gulp" (установить Gulp можно посредством выполнения в консоли следующей команды: npm install -g gulp-cli).

Последняя версия этого проекта (v.2.3.0) основана на Gulp 4 версии.

Если вы используете первую версию проекта, то дополнительно необходимо ещё установить пакетный менеджер Bower.

Node.js, Gulp и Bower. Инструменты, посредством которых можно создать окружение для комфортной разработки сайтов на Bootstrap 4

Установка Gulp:

Установка глобальной версии Gulp 4

Ключ -g указывает npm, что пакет необходимо загрузить не в текущую, а в общую папку.

Выполнение инсталляции программы Bower осуществляется аналогично Gulp (актуально только для версии проекта 1.0.0):

npm install -g bower

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

Далее следует распаковать архив и перенести файлы из каталога "gulp-project-bootstrap-4" в корневую директорию проекта.

Если нужна не текущая, а какая-то определённая версия (например, 1.0.0), то её можно загрузить со страницы Releases.

Следующий этап – это установка npm пакетов и их зависимостей. Для этого в консоли (должны находиться в корневой директории проекта) необходимо выполнить команду:

npm install

Данная команда установит все пакеты, которые нужны как для работы самого окружения, так и для фронтенда. Выполняет npm эти действия в соответствии с инструкциями, написанными в файле "package.json".

При использовании первой версии проекта (1.0.0), в которой используется менеджер пакетов Bower, необходимо выполнить ещё команду:

bower install

Данная программа установит фронтенд пакеты, указанные в файле "bower.json".

Как использовать Gulp окружение?

Открыть командную строку (путь должен указывать на корневую папку проекта) и ввести gulp (обычный режим):

gulp

После ввода этой команды запустится задача по умолчанию, т.е. "default". Эта задача в свою очередь запустит серию других задач: "build", "webserver" и "watch".

Задача "build" выполнит сборку проекта для продакшена (т.е. она запустит "clean:build", "html:build", "css:build", "js:build", "fonts:build" и "image:build"). Эти задачи поместят в папку "assets/build" результирующие файлы проекта.

Задача "webserver" предназначена для запуска локального веб-сервера с «живой перезагрузкой» страниц в браузере. С помощью него можно очень просто посмотреть проект и выполнить его тестирование.

Задача "watch" используется для отслеживания изменения исходных файлов в папке "assets/src" и выполнение если это призошло различных задач. Другими словами, она позволяет автоматически запускать необходимые задачи и поддерживать результирующие файлы (содержимое папки "assets/build") в актуальном состоянии.

Запуск gulp:

Запуск gulp

Кроме этого можно выполнять выборочную (самостоятельную) сборку той или иной части проекта.

Например, для сборки только CSS части сайта достаточно ввести команду:

gulp css:build

Список других задач:

gulp clean:build // для очистки каталога "assets/build"
gulp html:build // для сборки HTML файлов
gulp js:build // для сборки JS файлов
gulp fonts:build // для сборки шрифтов
gulp image:build // для сборки изображения

Описание Gulp окружения

В этом разделе разберём:

  • основные инструменты и файловую структуру Gulp окружения;
  • как осуществляется подключение исходников Bootstrap к проекту и их настройка;
  • как самостоятельно (с нуля) выполнить инициализацию Gulp проекта и установку зависимостей (без использования готового package.json)
  • как с нуля выполнить инициализацию Bower и установку фронтенд пакетов (без использования готового "bower.json")*;
  • содержимое файла сборщика проекта Gulp (gulpfile.js)

* Менеджер пакетов Bower не используется в проекте, начиная с версии 2.0.0.

Список инструментов

Окружение, предназначенное для разработки фронтенд проекта (сайта), построено на базе следующих инструментов:

  • Node.js (среды, в которой будет выполняться окружение);
  • npm (пакетного менеджера, входящего в Node.js; будет использоваться для загрузки Gulp, плагинов и фронтенд пакетов);
  • jQuery, Popover, Bootstrap (пакеты, которые будут использоваться для сборки css и js частей сайта);
  • Gulp и его плагины (будут использоваться для сборки проекта и выполнения других веб задач).

В первых версиях проекта дополнительно ещё использовался пакетный менеджер Bower. Он применялся за загрузки библиотек jQuery, Popover и Bootstrap. В версиях проекта, начиная с 2.0.0, загрузка данных библиотек выполняется посредством npm.

Файловая структура Gulp проекта

Файловую структуру проекта можно организовать по-разному. Это может зависеть как от предпочтений конкретного разработчика, так и от проекта, для которого она создаётся.

В данной статье будем придерживаться следующей структуры:

Файловая структура проекта на Bootstrap 4, сборка которого выполняется с помощью Gulp

В корне проекта расположена папка "assets" и файлы "gulpfile.js", "package.json". Файл "gulpfile.js" будет содержать задачи для сборщика проекта Gulp.

В первой версии проекта также использовались файлы ".bowerrc" и "bower.json". Файл "bower.json" - это конфигурационный файл менеджера Bower, на основании которого определялись необходимые для загрузки фронтенд пакеты. В данном проекте он использовался для загрузки Bootstrap, jQuery и Popper.

В папке "assets" находятся две папки: "src" (для исходных файлов) и "build" (для готовых файлов; в эту папку их будет помещать сборщик Gulp). В папке "src" расположены каталоги "fonts" (для шрифтов), "img" (для исходных изображений), "js" (для js-файлов), "style" (для стилей) и "template" (для HTML фрагментов) и файл "index.html".

В первой версии проекта в папке "src" ещё находилась директория "bower_components". Она предназначалась для компонентов, загрузка которых выполнялась с помощью Bower. В текущей версии её нет.

В каталоге "js" распологаются два файла: "main.js" и "my.js". Файл "my.js" используется для написания своих скриптов, а "main.js" – для определения списка файлов, содержимое которых необходимо будет включить в итоговый js-файл. Под итоговым понимается файл, который должен получиться на выходе (в каталоге "build").

Директория "style" отведена под стили. В данной директории находятся три файла: "main.scss" (содержит список файлов, содержимое которых необходимо включить в итоговый файл стилей), "my.scss" (используется для написания своих стилей) и "variables.scss" (содержит SCSS переменные, с помощью которых будем изменять стили Bootstrap 4, а также использовать его для создания своих переменных).

Файл "index.html" - это главная страница создаваемого проекта. Кроме "index.html" в данную директорию можно поместить и другие html страницы.

Директория "template" предназначена для помещения в неё фрагментов HTML страниц. Например, в данной директории можно создать файлы "head.html" и "footer.html", и импортировать их содержимое (используя синтаксис //= путь_к_файлу) сразу в несколько страниц. Это позволит более просто создавать и редактировать html страницы, т.к. отдельные части страниц уже будут находиться в отдельных файлах.

Подключение исходников Bootstrap 4 к проекту и их настройка

Как работать с исходниками Bootstrap 4

Существуют разные способы подключения фреймворка Bootstrap 4 к проекту, а также варианты работы с ним.

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

Исходные коды CSS стилей Bootstrap 4 написаны на языке SCSS и представлены посредством большого количества небольших файлов.

Список SCSS файлов (расположены в каталоге "node_modules/bootstrap/scss/"): "functions.scss", "variables.scss", "mixins.scss", "variables.scss", "print.scss", "reboot.scss", "type.scss", "images.scss", "code.scss", "grid.scss", "tables.scss", "forms.scss", "buttons.scss", "transitions.scss", "dropdown.scss" и др.

Каждой такой файл выполняет либо определённую служебную задачу, либо отвечает за стилизацию какой-то определённой функции фреймворка или компонента. Файлы SCSS имеют краткие и понятные имена. Используя только их можно достаточно точно понять назначение каждого из них.

Настройка или изменение дефолтных стилей Bootstrap 4 осуществляется посредством переопределения значений переменных SCSS. Все SCSS переменные для удобства собраны в одном месте (в файле "variables.scss"). Но, переопределять их значения желательно, конечно же, не в этом файле, а в своём (например, имеющим такое же имя "variables.scss", но находящемся в "assets/style/variables.scss").

Например, изменение цвета тем success и danger, осуществляется посредством изменения значений переменных $green и $red:

// Переопределение дефолтных значений переменных Bootstrap 4
$red:   #cc2eaa;
$green: #2ecc71;

Обратите внимание, что после копирования переменных Bootstrap 4 в свой файл CSS ("assets/style/variables.scss"), у них необходимо убрать метку !default.

Метка !default предназначена для установления SCSS переменной значения по умолчанию. Если же у SCSS переменной уже есть значение, то новое значение, если оно указано с ключом !default, установлено не будет.

Указать какие исходные SCSS файлы Bootstrap 4 должны участвовать при компиляции в CSS, а какие нет, выполняется посредством SCSS файла "assets/style/main.scss". Другими словами именно содержимое этого файла и будем определять тот набор стилей, который после компиляции будет подключен к веб-странице.

Кроме этого, к этому файлу также подключёны файлы "assets/style/variables.scss" (для переопределения переменных Bootstrap) и "assets/style/my.scss" (для создания своих стилей).

Содержимое файла "main.scss" (пример):

// Переопределение дефолтных значений переменных Bootstrap 4 и определение своих
@import "variables";

// Подключение нужных SCSS исходников Bootstrap 4
@import "../../../node_modules/bootstrap/scss/_functions";
@import "../../../node_modules/bootstrap/scss/_variables";
@import "../../../node_modules/bootstrap/scss/_mixins";
@import "../../../node_modules/bootstrap/scss/_root";
@import "../../../node_modules/bootstrap/scss/_reboot";
@import "../../../node_modules/bootstrap/scss/_type";
@import "../../../node_modules/bootstrap/scss/_images";
@import "../../../node_modules/bootstrap/scss/_code";
@import "../../../node_modules/bootstrap/scss/_grid";
@import "../../../node_modules/bootstrap/scss/_tables";
@import "../../../node_modules/bootstrap/scss/_forms";
@import "../../../node_modules/bootstrap/scss/_buttons";
@import "../../../node_modules/bootstrap/scss/_transitions";
@import "../../../node_modules/bootstrap/scss/_dropdown";
@import "../../../node_modules/bootstrap/scss/_button-group";
@import "../../../node_modules/bootstrap/scss/_input-group";
@import "../../../node_modules/bootstrap/scss/_custom-forms";
@import "../../../node_modules/bootstrap/scss/_nav";
@import "../../../node_modules/bootstrap/scss/_navbar";
@import "../../../node_modules/bootstrap/scss/_card";
@import "../../../node_modules/bootstrap/scss/_breadcrumb";
@import "../../../node_modules/bootstrap/scss/_pagination";
@import "../../../node_modules/bootstrap/scss/_badge";
@import "../../../node_modules/bootstrap/scss/_jumbotron";
@import "../../../node_modules/bootstrap/scss/_alert";
@import "../../../node_modules/bootstrap/scss/_progress";
@import "../../../node_modules/bootstrap/scss/_media";
@import "../../../node_modules/bootstrap/scss/_list-group";
@import "../../../node_modules/bootstrap/scss/_close";
@import "../../../node_modules/bootstrap/scss/_toasts";
@import "../../../node_modules/bootstrap/scss/_modal";
@import "../../../node_modules/bootstrap/scss/_tooltip";
@import "../../../node_modules/bootstrap/scss/_popover";
@import "../../../node_modules/bootstrap/scss/_carousel";
@import "../../../node_modules/bootstrap/scss/_spinners";
@import "../../../node_modules/bootstrap/scss/_utilities";
@import "../../../node_modules/bootstrap/scss/_print";

// Подключение своих SCSS файлов
@import "my";

Кроме этого, для работы некоторых компонентов Bootstrap 4 нужен ещё JavaScript код.

Список js-файлов Bootstrap 4 (находятся в каталоге "node_modules/bootstrap/js/dist/"): "util.js", "alert.js", "button.js", "carousel.js", "collapse.js", "dropdown.js", "modal.js", "tooltip.js", "popover.js", "scrollspy.js", "tab.js" и "toast.js".

Определение какие js-файлы фреймворка Bootstrap 4 необходимо включить в итоговый js-файл проекта, а какие нет, выполняется посредством "main.js".

Импортирование нужных файлов в результирующий build/main.js осуществляется посредством следующей конструкции:

//=  путь_к_файлу

Выполняет это действие будет Gulp плагин "gulp-rigger". Как его установить и подключить будет описано ниже.

В данный файл можно также импортировать jQuery, Popper (необходим для работы компонентов Dropdown, Tooltip и Popover) и при необходимости свои js-файлы.

Содержимое файла "main.js" (пример):

// Импортируем jQuery
//= ../../../node_modules/jquery/dist/jquery.js

// Импортируем Popper
//= ../../../node_modules/popper.js/dist/umd/popper.js

// Импортируем необходимые js-файлы Bootstrap 4
//= ../../../node_modules/bootstrap/js/dist/util.js
//= ../../../node_modules/bootstrap/js/dist/alert.js
//= ../../../node_modules/bootstrap/js/dist/button.js
//= ../../../node_modules/bootstrap/js/dist/carousel.js
//= ../../../node_modules/bootstrap/js/dist/collapse.js
//= ../../../node_modules/bootstrap/js/dist/dropdown.js
//= ../../../node_modules/bootstrap/js/dist/modal.js
//= ../../../node_modules/bootstrap/js/dist/tooltip.js
//= ../../../node_modules/bootstrap/js/dist/popover.js
//= ../../../node_modules/bootstrap/js/dist/scrollspy.js
//= ../../../node_modules/bootstrap/js/dist/tab.js
//= ../../../node_modules/bootstrap/js/dist/toast.js

// Импортируем другие js-файлы
//= my.js

Как с нуля выполнить инициализацию Gulp проекта и установку зависимостей?

Начинается разработка проекта обычно с создания файла "package.json" (манифеста).

Файл "package.json" будет содержать общую информацию о проекте (название, версию, описание, имя автора и др.), а также данные о пакетах, от которых этот проект зависит.

Для создания манифеста, необходимо перейти в корневую папку проекта и ввести команду:

npm init

Инициализация проекта:

Инициализация проекта

После ввода команды необходимо ответить на следующие вопросы:

  • имя проекта (name) – "bootstrap-4";
  • номер версии (version) – "2.0.0";
  • описание (description) – "Start project with use Bootstrap 4";
  • автор (author) – "itchief.ru";
  • git репозиторий (git repository) - "";
  • точка входа (entry point), тестовая команда (test command), лицензия (license), ключевые слова (keywords) – значения по умолчанию.

На вопрос «Is this ok?» ответим "yes" или нажмём Enter.

В результате в корневой папке проекта появится файл "package.json".

Теперь установим пакеты, которые будем использовать в проекте с помощью следующей команды:

npm install название_пакета --save-dev // установка пакета, при этом информация о нём, автоматически прописывается в секцию "devDependencies" файла "package.json"
npm install название_пакета --save-prod // установка пакета, при этом информация о нём, автоматически прописывается в секцию "dependencies" файла "package.json"

Ключ "--save-dev" или "--save-prod" определяет в какую секцию файла "package.json" попадёт информация о нём.

Список пакетов, которые будут использоваться в проекте:

npm install gulp --save-dev // установка gulp
npm install browser-sync --save-dev // установка browser-sync
npm install gulp-autoprefixer --save-dev // установка gulp-autoprefixer
npm install gulp-cache --save-dev // установка gulp-cache
npm install gulp-clean-css --save-dev // установка gulp-clean-css
npm install gulp-rimraf --save-dev // установка gulp-clean-css
npm install gulp-imagemin --save-dev // установка gulp-imagemin
npm install gulp-plumber --save-dev // установка gulp-plumber
npm install gulp-rigger --save-dev // установка gulp-rigger
npm install gulp-sass --save-dev // установка gulp-sass
npm install gulp-sourcemaps --save-dev // установка gulp-sourcemaps
npm install gulp-uglify --save-dev // установка gulp-uglify
npm install imagemin-jpeg-recompress --save-dev // установка imagemin-jpeg-recompress
npm install imagemin-pngquant --save-dev // установка imagemin-pngquant
npm install gulp-rename --save-dev // установка imagemin-pngquant

npm install jquery --save-prod
npm install popper.js --save-prod
npm install bootstrap --save-prod

После установки всех зависимостей, файл package.json будет иметь следующее содержимое:

{
  "name": "bootstrap-4",
  "version": "2.0.0",
  "description": "Start project with use Bootstrap 4",
  "author": "itchief.ru",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git://github.com/itchief/gulp-project-bootstrap-4.git"
  },
  "dependencies": {
    "jquery": "^3.4.1",
    "popper.js": "^1.14.7",
    "bootstrap": "^4.3.1"
  },
  "devDependencies": {
    "browser-sync": "^2.26.7",
    "gulp": "^4.0.2",
    "gulp-autoprefixer": "^6.1.0",
    "gulp-cache": "^1.1.2",
    "gulp-clean-css": "^4.2.0",
    "gulp-rimraf": "^0.2.2",
    "gulp-imagemin": "^6.0.0",
    "gulp-plumber": "^1.2.1",
    "gulp-rigger": "^0.5.8",
    "gulp-sass": "^4.0.2",
    "gulp-sourcemaps": "^2.6.5",
    "gulp-uglify": "^3.0.2",
    "imagemin-jpeg-recompress": "^6.0.0",
    "imagemin-pngquant": "^8.0.0",
    "gulp-rename": "^1.4.0"
  }
} 

Как с нуля выполнить инициализацию Bower и установку фронтенд пакетов?

Определим папку, в которую Bower будет загружать пакеты. Для этого создадим файл .bowerrc и введём в него следующее:

{
  "directory" : "assets/src/bower_components/"
}

Сохраним файл .bowerrc. Теперь все компоненты будут загружаться в каталог bower_components, находящийся в assets/src/.

Выполним инициализацию Bower (создадим файл-манифест bower.json). Создание файла bower.json можно осуществить с помощью команды (в корневой папке проекта):

bower init
Инициализация Bower
Инициализация Bower

После этого необходимо ответить на следующие вопросы:

  • имя проекта (name) – bootstrap-4;
  • описание (description) – Start project on Bootstrap 4 - itchief.ru;
  • автор (author) – itchief.ru;
  • установить установленные компоненты как зависимости (set currently installed components as dependencies) – Y (Да);
  • хотите вы отметить этот пакет как приватный, это предотвратит его случайную публикацию в реестре Bower (would you like to mark this package as private which prevents it from being accidentally published to the registry) – Y (Да);
  • на остальные вопросы оставим ответы, предлагаемые программой по умолчанию;

В результате этих действий будет создан файл bower.json.

Загрузим Bootstrap 4 и пакеты от которых он зависит (Popper и jQuery) в наш проект с помощью Bower.

Для этого в консоли необходимо ввести следующую команду:

bower install bootstrap#v4.0.0-beta --save

Ключ -save необходим для того, чтобы информацию о пакете записать в секцию dependencies файла bower.json.

В результате bower.json будет иметь следующее содержимое:

{
  "name": "bootstrap-4",
  "description": "Start project on Bootstrap 4 - itchief.ru",
  "authors": [
    "itchief.ru"
  ],
  "license": "ISC",
  "keywords": [],
  "homepage": "",
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "assets/src/bower_components/",
    "test",
    "tests"
  ],
  "dependencies": {
    "jquery": "^3.2.1",
    "bootstrap": "^v4.0.0-beta"
  }
}

Если вы не хотите инициализировать Bower (bower.json) с помощью команды bower init и устанавливать пакеты вручную, то можете просто создать файл bower.json (например, с помощью файлового менеджера) и вставить в него вышепредставленное текстовое содержимое. Для установки зависимостей в проект достаточно будет ввести следующую команду:

bower install

Описание файла сборщика проекта Gulp (gulpfile.js)

Все действия, выполненные до этого, были подготовительными. Весь функционал, который будет выполнять создаваемое окружение, будет определяться файлом "gulpfile.js".

Файл "gulpfile.js" представляет собой список задач.

Основные задачи которые будут выполнять этот файл:

  • сбор нескольких файлов стилей в один, компиляция полученного SCSS в CSS, добавление автопрефиксов, минимизация CSS и создание source map;
  • импорт всех необходимых js-файлов в один, минимизация этого файла и создание source map;
  • сбор html файла, перенос шрифтов, обработка (сжатие) картинок и автоматическое обновление страниц посредством Browser Sync.

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

Код файла "gulpfile.js" (при использовании Gulp 4):

'use strict';

/* пути к исходным файлам (src), к готовым файлам (build), а также к тем, за изменениями которых нужно наблюдать (watch) */
var path = {
    build: {
        html: 'assets/build/',
        js: 'assets/build/js/',
        css: 'assets/build/css/',
        img: 'assets/build/img/',
        fonts: 'assets/build/fonts/'
    },
    src: {
        html: 'assets/src/*.html',
        js: 'assets/src/js/main.js',
        style: 'assets/src/style/main.scss',
        img: 'assets/src/img/**/*.*',
        fonts: 'assets/src/fonts/**/*.*'
    },
    watch: {
        html: 'assets/src/**/*.html',
        js: 'assets/src/js/**/*.js',
        css: 'assets/src/style/**/*.scss',
        img: 'assets/src/img/**/*.*',
        fonts: 'assets/srs/fonts/**/*.*'
    },
    clean: './assets/build/*'
};

/* настройки сервера */
var config = {
    server: {
        baseDir: './assets/build'
    },
    notify: false
};

/* подключаем gulp и плагины */
var gulp = require('gulp'),  // подключаем Gulp
    webserver = require('browser-sync'), // сервер для работы и автоматического обновления страниц
    plumber = require('gulp-plumber'), // модуль для отслеживания ошибок
    rigger = require('gulp-rigger'), // модуль для импорта содержимого одного файла в другой
    sourcemaps = require('gulp-sourcemaps'), // модуль для генерации карты исходных файлов
    sass = require('gulp-sass'), // модуль для компиляции SASS (SCSS) в CSS
    autoprefixer = require('gulp-autoprefixer'), // модуль для автоматической установки автопрефиксов
    cleanCSS = require('gulp-clean-css'), // плагин для минимизации CSS
    uglify = require('gulp-uglify'), // модуль для минимизации JavaScript
    cache = require('gulp-cache'), // модуль для кэширования
    imagemin = require('gulp-imagemin'), // плагин для сжатия PNG, JPEG, GIF и SVG изображений
    jpegrecompress = require('imagemin-jpeg-recompress'), // плагин для сжатия jpeg	
    pngquant = require('imagemin-pngquant'), // плагин для сжатия png
    rimraf = require('gulp-rimraf'), // плагин для удаления файлов и каталогов
    rename = require('gulp-rename');

/* задачи */

// запуск сервера
gulp.task('webserver', function () {
    webserver(config);
});

// сбор html
gulp.task('html:build', function () {
    return gulp.src(path.src.html) // выбор всех html файлов по указанному пути
        .pipe(plumber()) // отслеживание ошибок
        .pipe(rigger()) // импорт вложений
        .pipe(gulp.dest(path.build.html)) // выкладывание готовых файлов
        .pipe(webserver.reload({ stream: true })); // перезагрузка сервера
});

// сбор стилей
gulp.task('css:build', function () {
    return gulp.src(path.src.style) // получим main.scss
        .pipe(plumber()) // для отслеживания ошибок
        .pipe(sourcemaps.init()) // инициализируем sourcemap
        .pipe(sass()) // scss -> css
        .pipe(autoprefixer()) // добавим префиксы
        .pipe(gulp.dest(path.build.css))
        .pipe(rename({ suffix: '.min' }))
        .pipe(cleanCSS()) // минимизируем CSS
        .pipe(sourcemaps.write('./')) // записываем sourcemap
        .pipe(gulp.dest(path.build.css)) // выгружаем в build
        .pipe(webserver.reload({ stream: true })); // перезагрузим сервер
});

// сбор js
gulp.task('js:build', function () {
    return gulp.src(path.src.js) // получим файл main.js
        .pipe(plumber()) // для отслеживания ошибок
        .pipe(rigger()) // импортируем все указанные файлы в main.js
        .pipe(gulp.dest(path.build.js))
        .pipe(rename({ suffix: '.min' }))
        .pipe(sourcemaps.init()) //инициализируем sourcemap
        .pipe(uglify()) // минимизируем js
        .pipe(sourcemaps.write('./')) //  записываем sourcemap
        .pipe(gulp.dest(path.build.js)) // положим готовый файл
        .pipe(webserver.reload({ stream: true })); // перезагрузим сервер
});

// перенос шрифтов
gulp.task('fonts:build', function () {
    return gulp.src(path.src.fonts)
        .pipe(gulp.dest(path.build.fonts));
});

// обработка картинок
gulp.task('image:build', function () {
    return gulp.src(path.src.img) // путь с исходниками картинок
        .pipe(cache(imagemin([ // сжатие изображений
            imagemin.gifsicle({ interlaced: true }),
            jpegrecompress({
                progressive: true,
                max: 90,
                min: 80
            }),
            pngquant(),
            imagemin.svgo({ plugins: [{ removeViewBox: false }] })
        ])))
        .pipe(gulp.dest(path.build.img)); // выгрузка готовых файлов
});

// удаление каталога build 
gulp.task('clean:build', function () {
    return gulp.src(path.clean, { read: false })
        .pipe(rimraf());
});

// очистка кэша
gulp.task('cache:clear', function () {
    cache.clearAll();
});

// сборка
gulp.task('build',
    gulp.series('clean:build',
        gulp.parallel(
            'html:build',
            'css:build',
            'js:build',
            'fonts:build',
            'image:build'
        )
    )
);

// запуск задач при изменении файлов
gulp.task('watch', function () {
    gulp.watch(path.watch.html, gulp.series('html:build'));
    gulp.watch(path.watch.css, gulp.series('css:build'));
    gulp.watch(path.watch.js, gulp.series('js:build'));
    gulp.watch(path.watch.img, gulp.series('image:build'));
    gulp.watch(path.watch.fonts, gulp.series('fonts:build'));
});

// задача по умолчанию
gulp.task('default', gulp.series(
    'build',
    gulp.parallel('webserver','watch')      
));

Код файла "gulpfile.js" содержит комментарии. С помощью них поясняется что выполняет тот или иной фрагмент инструкций.

Создание задачи в Gulp выполняется очень просто:

// создание gulp задачи (nametask – название задачи)
gulp.task('nametask', function() {
  // действия, которые должна выполнить задача...
});

Задачи в gulp построены очень просто. Их каркас действий в большинстве случаев можно представить так:

  • получить данные из исходных файлов;
  • обработать исходные данные посредством gulp плагинов;
  • сохранить полученный результат (файлы) в каталог "build".

Если используете Gulp 3, то содержимое файла "gulpfile.js" должно быть следующим:

'use strict';

/* параметры для gulp-autoprefixer */
var autoprefixerList = [
  'Chrome >= 45',
  'Firefox ESR',
  'Edge >= 12',
  'Explorer >= 10',
  'iOS >= 9',
  'Safari >= 9',
  'Android >= 4.4',
  'Opera >= 30'
];

/* пути к исходным файлам (src), к готовым файлам (build), а также к тем, за изменениями которых нужно наблюдать (watch) */
var path = {
  build: {
    html: 'assets/build/',
    js: 'assets/build/js/',
    css: 'assets/build/css/',
    img: 'assets/build/img/',
    fonts: 'assets/build/fonts/'
  },
  src: {
    html: 'assets/src/*.html',
    js: 'assets/src/js/main.js',
    style: 'assets/src/style/main.scss',
    img: 'assets/src/img/**/*.*',
    fonts: 'assets/src/fonts/**/*.*'
  },
  watch: {
    html: 'assets/src/**/*.html',
    js: 'assets/src/js/**/*.js',
    css: 'assets/src/style/**/*.scss',
    img: 'assets/src/img/**/*.*',
    fonts: 'assets/srs/fonts/**/*.*'
  },
  clean: './assets/build/*'
};

/* настройки сервера */
var config = {
  server: {
    baseDir: './assets/build'
  },
  notify: false
};

/* подключаем gulp и плагины */
var gulp = require('gulp'),  // подключаем Gulp
  webserver = require('browser-sync'), // сервер для работы и автоматического обновления страниц
  plumber = require('gulp-plumber'), // модуль для отслеживания ошибок
  rigger = require('gulp-rigger'), // модуль для импорта содержимого одного файла в другой
  sourcemaps = require('gulp-sourcemaps'), // модуль для генерации карты исходных файлов
  sass = require('gulp-sass'), // модуль для компиляции SASS (SCSS) в CSS
  autoprefixer = require('gulp-autoprefixer'), // модуль для автоматической установки автопрефиксов
  cleanCSS = require('gulp-clean-css'), // плагин для минимизации CSS
  uglify = require('gulp-uglify'), // модуль для минимизации JavaScript
  cache = require('gulp-cache'), // модуль для кэширования
  imagemin = require('gulp-imagemin'), // плагин для сжатия PNG, JPEG, GIF и SVG изображений
  jpegrecompress = require('imagemin-jpeg-recompress'), // плагин для сжатия jpeg	
  pngquant = require('imagemin-pngquant'), // плагин для сжатия png
  rimraf = require('gulp-rimraf'), // плагин для удаления файлов и каталогов
  rename = require('gulp-rename');

/* задачи */

// запуск сервера
gulp.task('webserver', function () {
  webserver(config);
});

// сбор html
gulp.task('html:build', function () {
  return gulp.src(path.src.html) // выбор всех html файлов по указанному пути
    .pipe(plumber()) // отслеживание ошибок
    .pipe(rigger()) // импорт вложений
    .pipe(gulp.dest(path.build.html)) // выкладывание готовых файлов
    .pipe(webserver.reload({ stream: true })); // перезагрузка сервера
});

// сбор стилей
gulp.task('css:build', function () {
  return gulp.src(path.src.style) // получим main.scss
    .pipe(plumber()) // для отслеживания ошибок
    .pipe(sourcemaps.init()) // инициализируем sourcemap
    .pipe(sass()) // scss -> css
    .pipe(autoprefixer({ // добавим префиксы
        browsers: autoprefixerList
    }))
    .pipe(gulp.dest(path.build.css))
    .pipe(rename({ suffix: '.min' }))
    .pipe(cleanCSS()) // минимизируем CSS
    .pipe(sourcemaps.write('./')) // записываем sourcemap
    .pipe(gulp.dest(path.build.css)) // выгружаем в build
    .pipe(webserver.reload({ stream: true })); // перезагрузим сервер
});

// сбор js
gulp.task('js:build', function () {
  return gulp.src(path.src.js) // получим файл main.js
    .pipe(plumber()) // для отслеживания ошибок
    .pipe(rigger()) // импортируем все указанные файлы в main.js
    .pipe(gulp.dest(path.build.js))
    .pipe(rename({ suffix: '.min' }))
    .pipe(sourcemaps.init()) //инициализируем sourcemap
    .pipe(uglify()) // минимизируем js
    .pipe(sourcemaps.write('./')) //  записываем sourcemap
    .pipe(gulp.dest(path.build.js)) // положим готовый файл
    .pipe(webserver.reload({ stream: true })); // перезагрузим сервер
});

// перенос шрифтов
gulp.task('fonts:build', function () {
  return gulp.src(path.src.fonts)
    .pipe(gulp.dest(path.build.fonts));
});

// обработка картинок
gulp.task('image:build', function () {
  return gulp.src(path.src.img) // путь с исходниками картинок
    .pipe(cache(imagemin([ // сжатие изображений
      imagemin.gifsicle({ interlaced: true }),
      jpegrecompress({
        progressive: true,
        max: 90,
        min: 80
      }),
      pngquant(),
      imagemin.svgo({ plugins: [{ removeViewBox: false }] })
    ])))
    .pipe(gulp.dest(path.build.img)); // выгрузка готовых файлов
});

// удаление каталога build 
gulp.task('clean:build', function () {
  return gulp.src(path.clean, { read: false })
    .pipe(rimraf());
});

// очистка кэша
gulp.task('cache:clear', function () {
  cache.clearAll();
});

// сборка
gulp.task('build', [
  'clean:build',
  'html:build',
  'css:build',
  'js:build',
  'fonts:build',
  'image:build'
]);

// запуск задач при изменении файлов
gulp.task('watch', function () {
  gulp.watch(path.watch.html, ['html:build']);
  gulp.watch(path.watch.css, ['css:build']);
  gulp.watch(path.watch.js, ['js:build']);
  gulp.watch(path.watch.img, ['image:build']);
  gulp.watch(path.watch.fonts, ['fonts:build']);
});

// задача по умолчанию
gulp.task('default', [
  'build',
  'webserver',
  'watch'      
]);

Комментарии:

  1. Dmitry
    03 мая 2020, 15:54
    Здравствуйте!
    Извиняюсь, вопрос скорей не по существу и не к вам. Но очень надеюсь на Вашу помощь. Ушел с винды, перешел на ubuntu 20. Сборка работает в целом нормально, иногда не проходят изменения, терминал молчит, ошибок не выводит, время не меняется, но это редко. А вот как сборку подружить с ламп сервером не могу разобраться. Перестает обновляться, причем странно как то. Если что то менять в файле из template то обновление проходит один раз и все кэш. Если в основном файле то можно обновится раз 10, и опять кэш. Если допустим в файле из template поменял что нибудь а страница в браузере не обновилась перехожу в родительский файл меняю что нибудь и обновления проходят. Если можно подскажите пожалуйста на что обратить внимание. Спасибо!
    1. Александр Мальцев
      03 мая 2020, 16:02
      Здравствуйте! По 20.04 версии не подскажу, использую 18.04. Устанавливаю apache, php, mysql самостоятельно, набор LAMP не использую.
      1. Dmitry
        03 мая 2020, 16:19
        а где нибудь можно почитать про отдельную установку и про настройку? не просто так спрашиваю, с этим ламп мозг закипает. месяца 2 уже с ним воюю, все что есть перечитал уже. А так от ubuntu просто в шоке, очень нравится, все летает, в бетке была лучше чем вин 10 из коробки

        значит моя проблема в ламп?
        1. Александр Мальцев
          05 мая 2020, 15:35
          LAMP в Ubuntu устанавливается так:
          sudo tasksel install lamp-server
          
          Про проблемы не знаю, попробуйте поставить не бету, а финальный релиз 20.04.
    2. fet
      18 апреля 2020, 12:44
      Здравствуйте, скачал по новой проект, все установил как у вас описано, все отлично работает, вот только Autoprefixer не работает, подскажите что надо поправить?
      1. Александр Мальцев
        18 апреля 2020, 15:38
        Здравствуйте!
        А что с Autoprefixer не так?
        Если нужны настройки не по умолчанию, а какие-то конкретные, то тогда, их следует выставить, например, в «packege.json»:
        {
          ...
          "browserslist": [
            "> 1%",
            "ie 10"
          ]
        }
        
        1. Ion
          01 мая 2020, 03:02
          Привет!.

          У меня тоже не работает префикс. Пробовал задать browserlist в package.json но не помогло.

          И еще один вопрос: как добавить видео к проекту, после компиляции (команда gulp) у меня видео удаляется из папки video что я создал.
          1. Александр Мальцев
            01 мая 2020, 13:55
            Привет!
            А для каких браузеров не создаются префиксы, может они не входят в список поддержки, которые вы указали в browserslist.
            Исходные файлы не должны удаляться. Может они не переносятся в build? В этом случае добавьте код как это сделано для fonts.
            1. Ion
              03 мая 2020, 20:30
              Префиксы у меня не для одного браузера не добавляются. Проверил в ie, firefox, opera.
              Может browserlist нужно отдельно скачать github.com/browserslist/browserslist#browserslist-?

              И насчет добавление видео к проекту спасибо огромное — получилось!
              1. Александр Мальцев
                04 мая 2020, 10:03
                Например, мне нужна поддержка IE10 и других браузеров процент использования которых превышает 1%.
                Чтобы это выполнить, мне нужно открыть файл «package.json» и добавить в него после devDependencies раздел browserslist:
                {
                  ...
                  "devDependencies": {
                    ...  
                  },
                  "browserslist": [
                    "> 1%",
                    "ie 10"
                  ]
                }
                
                Теперь чтобы проверить, я открою файл «my.scss» и добавлю в него, например, следующие стили:
                .flex-container {
                  display: flex;
                  flex-direction: column;
                }
                
                После запуска gulp открою файл «main.css» в build и проверю добавил ли gulp-autoprefixer стили с префиксами для браузеров (в данном случае для IE10 и браузеров с долей > 1%):
                ...
                .flex-container {
                  display: -ms-flexbox;
                  display: flex;
                  -ms-flex-direction: column;
                  flex-direction: column;
                }
                
                Как видно они есть, значит gulp-autoprefixer отрабатывает отлично.
                Если у вас что-то не работает может быть вы неправильно описали поддержку необходимых браузеров в browserslist.
                1. Ion
                  04 мая 2020, 10:55
                  prnt.sc/sajclh — Спасибо указал last 4 versions и заработал prnt.sc/sajfep. Спасибо большое! Удачи вам во всем!
      2. Роман
        17 апреля 2020, 15:14
        Спасибо большое за сборку. Она слегка устарела и требует обновления:
        1) gulp-rimraf — этот плагин объявлен устаревшим в пользу del. Впрочем, несмотря на это, после обновления до 1.0.0 он продолжает работать.
        2) gulp-imagemin — при попытке обновить до следующей мажорной версии, перестаёт работать сборка. Максимум, до которого можно его обновлять, это 6.2.0.

        Всё остальное обновил до последней версии и всё нормально заработало.
        Ещё раз большое спасибо. Будет очень круто, если Вы её обновите и поправите.
        1. Александр Мальцев
          18 апреля 2020, 15:34
          Пожалуйста! Обновил сборку (gulp-rimraf заменил на del).
          А что не так с gulp-imagemin? На Windows 10 устанавливается всё отлично.
          Если вы используете WSL (Ubuntu), то перед выполнением команды npm install установите пакет dh-autoreconf:
          sudo apt-get install dh-autoreconf
          Данный пакет необходим для успешной установки gifsicle входящей в состав gulp-imagemin.
        2. fet
          10 апреля 2020, 19:52
          Здравствуйте, перестал работать Autoprefixer, выдает вот такую ошибку, подскажите пжл. что может быть?

          monosnap.com/file/mf4OWDgSNyc2e6VpZEllS1rdEZV95v

          Как указано npm update я сделал, но ничего не помогает ((
          1. Александр Мальцев
            13 апреля 2020, 12:39
            Уберите для autoprefixer аргументы (он по умолчанию имеет оптимальные настройки):
            .pipe(autoprefixer()) // добавим префиксы
            
          2. fet
            04 апреля 2020, 15:12
            Здравствуйте
            Как php прикрутить к Вашей сборке? Ниже видел, но там к старой версии, а как к новой версии? подскажите пжл.
            1. Александр Мальцев
              06 апреля 2020, 16:10
              Здравствуйте! Если вам нужная совместная разработка, то в gulpfile.js для BrowserSync можно указать опцию proxy:
              ...
              /* настройки сервера */
              var config = {
                  proxy: "mysite.ru",
                  notify: false
              };
              
              Далее просто запускаете, например, apache сервер. Мне в последнее время очень нравится использовать для этого систему WSL в Windows 10, т.к. она работает очень быстро. После этого gulp.
            2. fet
              30 марта 2020, 01:55
              Спасибо, все отлично работает, но не работает нормально слайдер и меню, то есть нет плавности, меню просто открывается но не выезжает плавно и слайдер меняется картинка но не листается плавно, в чем может быть проблема?
              Свой слайдер подключаю все ок работает есть плавность, не пойму что не так, в консоли ошибок нет, уже голова кепит
              Захожу на официальный сайт bootstrap беру готовый код со всеми стилями и скриптами подключенным через cdn вставляю туда код карусели и бутстраповской и тоже не листается слайдер просто меняется картинка, может вы сталкивались и меню так же открывается но нет плавности slidetoggle
              1. Александр Мальцев
                30 марта 2020, 16:33
                Пожалуйста! Информация по анимации карусели, а также почему она может не работать приведена в этом комментарии.
              2. Оксана
                21 марта 2020, 04:35
                Александр, спасибо большое за статью.
                У меня вопрос: как правильно удалить из css неиспользуемые стили? Не хочется весь bootstrap тянуть с собой.
                Раньше для этого использовался UnCSS, но он устарел. Можно его чем-то заменить?
                Спасибо.
                1. Александр Мальцев
                  21 марта 2020, 05:04
                  Здравствуйте!
                  Так это делается простым комментированием подключаемых файлов в main.scss.
                  Если, например, не нужны Bootstrap компоненты Pagination, Badge, Alert и Progress, то их следует закомментировать:
                  ...
                  // @import "../../../node_modules/bootstrap/scss/_pagination";
                  // @import "../../../node_modules/bootstrap/scss/_badge";
                  @import "../../../node_modules/bootstrap/scss/_jumbotron";
                  // @import "../../../node_modules/bootstrap/scss/_alert";
                  // @import "../../../node_modules/bootstrap/scss/_progress";
                  ...
                  
                  1. Оксана
                    23 марта 2020, 03:52
                    Я не совсем это имею ввиду. Например, я задействую таблицы, но далеко не все классы из файла _tables мне нужны. Хочется пробежаться по файлу и оставить только те классы, которые используются в моем html-файле.
                    1. Александр Мальцев
                      23 марта 2020, 15:34
                      Исходные стили Bootstrap 4 находятся в SCSS файлах. Чтобы SCSS код превратить в CSS его необходимо компилировать. При этом стили в этих файлах созданы с использованием переменных. Изменяя им значения, мы можем получить ту или иную сборку Bootstrap (CSS-код). Для этого нам и нужен соответствующий набор инструментов, описанный в этой статье.

                      Если вы хотите использовать какие-то определённые стили из этого фреймворка, то просто скопируйте их в свой CSS файл. Потому что в этом случае определить какие стили вам нужны, а какие нет, можете только вы сами. Нет никакого волшебного инструмента, который 100% точно может определить нужны ли вам какие-то определенные стили нет. Например, если вы добавляете элемент динамически на страницу или какой-то класс к элементу с помощью JavaScript.

                      Если, вам не нужные какие-то определённые темы (например, danger, success), то они очень просто удаляются с помощью переменных. Для этого вы просто устанавливаете новые значения переменным и получаете на выходе соответствующий CSS код.
                      При этом не вижу смысла, если вы используете Bootstrap, что-то удалять, чтобы получить экономию в 20Кбайт, чтобы после этого получить не обновляемый на новые версии CSS код. Это экономия будет меньше, чем одна небольшая картинка. Это практически не скажется на скорости загрузки сайта.
                      1. Оксана
                        24 марта 2020, 03:23
                        Александр, спасибо за такой развернутый ответ.
                        Теперь все понятно. Подключила таким же способом Font Awesome — очень удобно. Еще раз спасибо!)
                2. Сергей
                  14 февраля 2020, 22:32
                  Доброго здоровья.

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

                  Боюсь обновлять версии новых пакетов.
                  ncu предлагает следующее:
                  popper.js          ^1.14.7  →  ^1.16.1
                   bootstrap           ^4.3.1  →   ^4.4.1
                   gulp-autoprefixer   ^6.1.0  →   ^7.0.1
                   gulp-cache          ^1.1.2  →   ^1.1.3
                   gulp-rimraf         ^0.2.2  →   ^1.0.0
                   gulp-imagemin       ^6.0.0  →   ^7.1.0
                   gulp-rename         ^1.4.0  →   ^2.0.0
                  Будут ли совместимы новые версии с предыдущими?
                  Спасибо. Сергей
                  1. Сергей
                    14 февраля 2020, 23:00
                    Проверил после обновления до указанных выше версий — всё работает!
                    [====================] 18/18 100%
                    All dependencies match the latest package versions :)
                    Т.е. по состоянию на 14 февраля 2020 года все обновления совместимы с вашей удачной сборкой GULP.

                    Обновлённые версии пакетов по состоянию на 14.02.2020
                    popper.js           →   ^1.16.1
                    bootstrap           →   ^4.4.1
                    gulp-cache          →   ^1.1.3
                    gulp-rimraf         →   ^1.0.0
                    gulp-imagemin       →   ^7.1.0
                    gulp-rename         →   ^2.0.0
                    gulp-autoprefixer   →   ^7.0.1
                    
                    До этого имел большие проблемы с обновлением Gulp 3 до версии Gulp 4. Теперь боюсь любых обновлений.
                    1. Сергей
                      15 февраля 2020, 09:11
                      После обновления gulp-imagemin с 6.0.0 версии на v.7.1.0 обнаружил проблему в работе.
                      Разбираться не стал, вернул значение в файле package.json на «gulp-imagemin»: "^6.0.0",
                      Вновь всё заработало.
                      Возможно эта проблема только в моей сборке, но будьте осторожны при обновлении пакета:
                      gulp-imagemin ^6.0.0 → ^7.1.0
                      1. Сергей
                        15 февраля 2020, 09:17
                        Зато с остальным нет проблем.
                        Очень понравилась понятная иерархия сборки — всё разложено по полочкам, трудно запутаться, не оставляет возможности думать: «Где, что лежит»?
                        1. Александр Мальцев
                          15 февраля 2020, 15:03
                          Спасибо за отзыв. В большинстве случаев обновление пакетов до новых версий проходит гладко. Но, конечно, бывают исключения. Поэтому после обновления нужно, конечно, проверять, чтобы ничто не сломалось.
                  2. Sanjar
                    08 февраля 2020, 19:51
                    Здравствуйте. Подскажите как правильно подключить библиотеку. Многие в сети пишут что бовер уже умер. Подскажите пжл как правильно подключат фонтан авесома и силк слайдер. И правильно ли бовер умер?
                    1. Александр Мальцев
                      09 февраля 2020, 15:47
                      Здравствуйте.
                      Просто сейчас Bower уже не такой популярный как раньше, все пакеты есть в npm. В этом окружение используется только npm.
                      Процесс установки slick карусели и подключения её к проекту осуществляется так:
                      1. Установка пакета slick-carousel с помощью npm:
                      npm install slick-carousel
                      
                      2. Включение стилей карусели в файл «main.scss»:
                      @import "../../../node_modules/slick-carousel/slick/slick.scss";
                      
                      3. Включение скрипта карусели в файл «main.js»:
                      //= ../../../node_modules/slick-carousel/slick/slick.js
                      
                      Установка и подключение Font Awesome и других пакетов осуществляется аналогично. Т.е. устанавливаете пакет с помощью npm, затем подключаете стили (если они есть) в «main.scss» и скрипты (если они есть) в «main.js».
                      1. Sanjar
                        09 февраля 2020, 07:13
                        И можно ли удалять папку node_modules после завершения проекта? А то папка весить много
                        1. Александр Мальцев
                          09 февраля 2020, 15:58
                          Конечно, она нужна только для разработки.
                      2. Artodox
                        19 декабря 2019, 18:19
                        Добрый день Александр, не мгли бы помочь разобраться в чем проблема, всю голову сломал: при добавлении картинки в проект появляется ошибка:

                        [16:12:48] Using gulpfile /mnt/k/WEB-Dev/G4/gulpfile.js
                        [16:12:48] Starting 'default'…
                        [16:12:48] Starting 'build'…
                        [16:12:48] Starting 'clean:build'…
                        [16:12:48] Finished 'clean:build' after 54 ms
                        [16:12:48] Starting 'html:build'…
                        [16:12:48] Starting 'css:build'…
                        [16:12:48] Starting 'js:build'…
                        [16:12:48] Starting 'fonts:build'…
                        [16:12:48] Starting 'image:build'…
                        [16:12:54] Finished 'js:build' after 5.92 s
                        [16:12:54] Finished 'css:build' after 6.21 s
                        [16:12:54] 'image:build' errored after 6.24 s
                        [16:12:54] Error in plugin «gulp-cache»
                        Message:
                        spawn /mnt/k/WEB-Dev/G4/node_modules/jpeg-recompress-bin/vendor/jpeg-recompress ENOENT
                        Details:
                        errno: ENOENT
                        code: ENOENT
                        syscall: spawn /mnt/k/WEB-Dev/G4/node_modules/jpeg-recompress-bin/vendor/jpeg-recompress
                        path: /mnt/k/WEB-Dev/G4/node_modules/jpeg-recompress-bin/vendor/jpeg-recompress
                        spawnargs: --quiet,--min,80,--max,90,--strip,/tmp/23d8c896-de73-4f24-acf0-9d987990e7cc,/tmp/a1baadb0-f348-4b05-aba0-ab6972001dd1
                        killed: false
                        stdout:
                        stderr:
                        failed: true
                        signal: null
                        cmd: /mnt/k/WEB-Dev/G4/node_modules/jpeg-recompress-bin/vendor/jpeg-recompress --quiet --min 80 --max 90 --strip /tmp/23d8c896-de73-4f24-acf0-9d987990e7cc /tmp/a1baadb0-f348-4b05-aba0-ab6972001dd1
                        timedOut: false
                        fileName: /mnt/k/WEB-Dev/G4/assets/src/img/intro1.jpg
                        domainEmitter: [object Object]
                        domainThrown: false

                        [16:12:54] 'build' errored after 6.31 s
                        [16:12:54] 'default' errored after 6.31 s
                        [16:12:54] The following tasks did not complete: html:build, fonts:build
                        [16:12:54] Did you forget to signal async completion?

                        заранее благодарен.
                        1. Александр Мальцев
                          21 декабря 2019, 05:03
                          Привет! Не сталкивался с таким. Попробуй переустановить или обновить пакет. Ошибка происходит только для одной определённой картинки или для всех?
                        2. fet
                          15 ноября 2019, 21:58
                          Все установил как у вас описано, все отлично работает, но при смене стилей в my.scss и сохранение страницы не обновляется браузер, а при сохранении в index.html браузер обновляется и изменения происходят, подскажите что может быть не так? где поправить? ошибки никакой не выдает ((
                          1. fet
                            16 ноября 2019, 10:14
                            Все разобрался, путь поменялся на css/main.min.css ((( а у меня стоял css/main.css
                          2. fet
                            13 ноября 2019, 23:32
                            Здравствуйте, все установил, как в описании.
                            Но появляется вот такая ошибка:
                            itchief.ru/assets/uploadify/6/0/4/60476d607fa9fd4ce465bd361eacaf32s.jpg
                            Подскажите, что я сделал не так и где можно поправить?
                            1. Александр Мальцев
                              14 ноября 2019, 13:28
                              В статье была ссылка на предыдущую версию проекта. Изменил ссылку, теперь она ведёт на новый архив. В этой версии код обновлен для корректной работы пакета gulp-autoprefixer.
                              Подключение owl.carousel можно осуществить так.
                              1. В main.scss вставить:
                              @import "../../../node_modules/owl.carousel/dist/assets/owl.carousel";
                              
                              2. В main.js добавить следующее:
                              //= ../../../node_modules/owl.carousel/dist/owl.carousel.js
                              
                              1. fet
                                16 ноября 2019, 10:15
                                по поводу @import я подключал стили с расширением .css, а надо без него в sass файлах, убрал расширения и все подгрузилось
                                1. Александр Мальцев
                                  16 ноября 2019, 15:32
                                  Молодец, что разобрался. Расширение .css указывать конечно не нужно было.
                            2. Artodox
                              07 ноября 2019, 12:03
                              Добрый день Александр,
                              спасибо за сборку! Самая ясная и стабильная из всех, что пробовал. Я занимаюсь графическим дизайном и версткой, но в программировании не силен. Проблема в том, что никак не могу подключить свой «woff2» шрифт к сборке, не подскажете процедуру. Заранее благодарен.
                              1. Александр Мальцев
                                07 ноября 2019, 14:36
                                Привет! Спасибо за отзыв.
                                Для этого нужно в папку «src/fonts» поместить нужные шрифты. Например, поместим в неё «Roboto-Regular.woff2».
                                После этого этот шрифт нужно подключить.
                                Для этого в файл «my.scss» нужно, например, добавить следующее:
                                @font-face {
                                  font-family: "Roboto";
                                  src: url("../fonts/Roboto-Regular.woff2") format("woff2");
                                  font-style: normal;
                                  font-weight: normal;
                                }
                                
                                После этого его можно использовать, например:
                                h1 {
                                  font-family: Roboto, sans-serif;
                                }
                                
                                1. Artodox
                                  07 ноября 2019, 15:49
                                  Спасибо, все работает, я немного перемудрил :)
                                  Еще один вопрос: у меня почему то в build main.css(142kb) меньше, чем main.min.css(169kb)
                              2. Дмитрий
                                22 октября 2019, 11:58
                                Здравствуйте, Александр! Спасибо за данную статью все отлично запускается и работает, особенно хочу отметить эффективное сжатие изображений) У меня такой вопрос: bower на своем сайте сам же рекомендует вместо bower использовать yarn, мне немного не понятно yarn устанавливается отдельно на windows и уже потом с помощью yarn-команд устанавливается gulp или же есть какой-то способ внедрить yarn в gulp?
                                1. Александр Мальцев
                                  22 октября 2019, 14:03
                                  Привет! Спасибо за добрые слова.
                                  Сейчас в проекте bower не используется, все пакеты устанавливаются через npm.
                                  Если хотите переделать через yarn, то его конечно нужно сначала установить. Но перед установкой yarn нужно установить Node.js, т.к. он от него зависит. После этого установите yarn.
                                  Установка gulp глобально:
                                  yarn global add gulp
                                  
                                  Установка пакетов:
                                  yarn install
                                  
                                  1. Дмитрий
                                    22 октября 2019, 14:15
                                    Теперь стало более ясно, спасибо большое!))
                                2. AlexD
                                  11 октября 2019, 09:26
                                  Александр, я специально зарегистрировался, чтобы выразить вам огромную благодарность за материал. Я два дня потратил на поиски ответов и столкнулся с тем, что люди просто не понимают, о чем пишут. Но на вашем сайте я нашел то, что мне очень помогло и очень нужно. Еще раз спасибо!
                                  1. Александр Мальцев
                                    11 октября 2019, 13:32
                                    Я рад что понравилось. Спасибо за отзыв.
                                  2. Татьяна
                                    13 сентября 2019, 17:40
                                    Хочу сказать спасибо, отличная работа, все запустилось с первой попытки. И высказать пожелание скорейшего выхода дальнейших Ваших статей и конкретно примера о котором Вы писали выше. Еще раз спасибо за Вашу работу.
                                    1. Александр Мальцев
                                      14 сентября 2019, 03:12
                                      Спасибо за отзыв.
                                    2. Stan
                                      04 августа 2019, 01:23
                                      Александр, приветствую!

                                      Отличная работа и мануал, почёт и уважение. Стал пользоваться вашим решением, до этого пользовался примерным решением и менял от версии к версии. Grunt тоже был в ходу :)

                                      Из моих примечаний, что лучше не «пришивать» jquery и popper, а копировать в проект при разработке. Продакшн версию конечно же лучше сшить.
                                      Хотя палка о двух концах. Здесь ломали копья в споре лучше CDN или своё.

                                      Ну и дополнение

                                      Добавим путь

                                      /* пути к исходным файлам (src), к готовым файлам (build), а также к тем, за изменениями которых нужно наблюдать (watch) */
                                      var path = {
                                          build: {
                                              html: 'assets/build/',
                                              .......
                                              .......
                                              copy: 'assets/build/js/vendor/'
                                          },
                                      
                                      Указываем исходники

                                      var sourceFiles = ['node_modules/jquery/dist/jquery.js','node_modules/popper.js/dist/umd/popper.js'];
                                      
                                      Подключим (предварительно указав в package.json «gulp-copy»: "^4.0.1")

                                      var copy  = require('gulp-copy'); // плагин для копирования файлов
                                      
                                      Добавим задачу

                                      // копирование js
                                      gulp.task('copy:build', function () {
                                          return gulp.src(sourceFiles)
                                              .pipe(gulp.dest(path.build.copy));
                                      });
                                      
                                      И добавим в сборку

                                      // сборка
                                      gulp.task('build',
                                          gulp.series('clean:build',
                                              gulp.parallel(
                                                  ......
                                                  'copy:build',
                                                  ......
                                              )
                                          )
                                      );
                                      
                                      И не забудем в подключении скриптов указать верный путь: js/vendor/

                                      По аналогии можно копировать что угодно и куда угодно.
                                      1. Denis
                                        13 августа 2019, 15:05
                                        Добрый день!
                                        Все сделал по инструкции но, что, то пошло не так.

                                        [14:52:47] Finished 'copy:build' after 412 ms
                                        
                                          Replace Autoprefixer browsers option to Browserslist config.
                                          Use browserslist key in package.json or .browserslistrc file.
                                        
                                          Using browsers option cause some error. Browserslist config
                                          can be used for Babel, Autoprefixer, postcss-normalize and other tools.
                                        
                                          If you really need to use option, rename it to overrideBrowserslist.
                                        
                                          Learn more at:
                                          https://github.com/browserslist/browserslist#readme
                                          https://twitter.com/browserslist
                                        Помогите устранить ошибку.
                                        1. Denis
                                          13 августа 2019, 15:26
                                          Проблема решена!
                                          В доках pipe заменить browsers: ['last 2 versions'] на overrideBrowserslist: ['last 2 versions'] и тогда предупреждение пропадает))
                                          .pipe(autoprefixer({
                                                      overrideBrowserslist:  ['last 2 versions'],
                                                      cascade: false
                                                  }))
                                          1. fet
                                            14 ноября 2019, 22:48
                                            Спасибо помогло
                                        2. Александр Мальцев
                                          04 августа 2019, 10:44
                                          Привет!
                                          Благодарю за отзыв и за подробный рецепт, многим пригодится.
                                          А так, да, использовать CDN или нет, это конечно же личные предпочтения и решать каждому.
                                        3. Иван
                                          21 июля 2019, 00:57
                                          Здравствуйте! Спасибо за полезную статью. Хочу один момент уточнить, когда импортируем файлы бутстрап, там ведь не обязательно прописывать спереди исходника нижнее подчеркивание.
                                          // подключение нужных SCSS исходников Bootstrap 4
                                          @import "../../../node_modules/bootstrap/scss/_functions";
                                          .......................
                                          
                                          Я имею ввиду здесь: _functions. Можно просто
                                          @import "../../../node_modules/bootstrap/scss/functions";
                                          Мы ведь только импортируем эти фалы. На сколько я понял из документации, файлы с нижним подчеркиванием в начале, не компилируются… Но в данном случае мы их не компилируем, а импортируем в файл, который и будет в последствии скомпилирован. Верно ли я понял, что не обязательно тут писать "_"?
                                          Ведь даже в основном файле bootstrap.scss импортируют без этих подчеркиваний.
                                          1. Александр Мальцев
                                            21 июля 2019, 01:55
                                            Да, когда вы указываете компилятору какую-то папку, то он в ней переводит все SCSS файлы в CSS за исключением тех, которые начинаются с нижнего подчёркивания. Эти файлы, начинающиеся с нижнего подчеркивания, игнорируются. Эта принятая в этом языке условность. Т.е. если файл начинается с нижнего подчёркивания, то он является фрагментом и его нужно игнорировать. Он используется в каком-то другом файле.

                                            В этом окружении мы указываем компилятору конкретный файл «assets/src/style/main.scss», в который всё импортировано. Если мы бы указали ему папку, то нужно было бы тогда следить за файлами. Т.е. те, которые нам не нужно включать в build и они являются фрагментом другого файла указывать их с нижнем подчеркиванием. А те файлы, которые должны быть самостоятельными и находиться в результирующей папки (т.е. build/css) указывать без нижнего подчеркивания.

                                            А так в этом окружении мы указываем конкретный файл, то неважно будут они с нижним подчеркиванием или нет. Но лучше по правилам указывать файлы с нижним, чтобы для себя понимать, что они являются частью другого.

                                            А в «gulpfile.js» да, нижнее подчеркивание можно опустить, не указывать.
                                            1. Иван
                                              24 сентября 2019, 17:52
                                              Добрый день! Подскажите ещё, я правильно понял, что файлы бутстрап будут каждый раз пересобираться при изменении нашего файла scss? Грамотно ли будет для бутстрап отдельный таск просто создать? Ведь по идее его только один раз скомпилировать нужно. Или я не прав?
                                              1. Александр Мальцев
                                                25 сентября 2019, 14:21
                                                Привет! Да, файлы будут каждый раз пересобираться. Это конечно правильно, только если не нужно брать его по дефолту. Т.к. в большинстве случаев нужно настраивать Bootstrap (устанавливать SASS переменным другие значения). После этого чтобы эти изменения увидеть, его нужно пересобрать. Вот такой процесс.
                                                Что хотите сократить? Если нужен Bootstrap по дефолту, то просто подключите его отдельно, например, через CDN.
                                          2. Иван
                                            01 июля 2019, 12:50
                                            Добрый день
                                            Если необходимо, что бы были вложенные папки для html — что нужно прописать в gulpfile.js

                                            тесть необходимо, чтобы вложенные HTML в папки также переносились в билд с такой же структурой

                                            prntscr.com/o8yepw
                                            1. Александр Мальцев
                                              21 июля 2019, 00:23
                                              Привет!
                                              Для этого нужно создать папку pages в папке src. Перенести существующий файл «index.html» в эту папку, т.е. в pages.
                                              Открыть этот файл и поменять пути к шаблонам «head.html» и «footer.html»:
                                              ...
                                              //= ../template/head.html
                                              ...
                                              //= ../template/footer.html
                                              ...
                                              
                                              После этого открыть файл «gulpfile.js» и поменять в нём путь к исходным html:
                                              var path = {
                                                  ...
                                                  src: {
                                                      html: 'assets/src/pages/**/*.html',
                                                  ...
                                              
                                              Добавил в проект на Github новую ветку with-nested-structure.
                                            2. Natalia
                                              23 июня 2019, 19:38
                                              Здравствуйте, Александр.
                                              Спасибо за статью.
                                              Пытаюсь установить и запустить проект. Дошла до запуска команды gulp. Появляется сообщение:
                                              $ gulp
                                              [23:15:14] Using gulpfile ~\Documents\WebProjects\test\gulpfile.js
                                              C:\Program Files\nodejs\node_modules\gulp\bin\gulp.js:129
                                              gulpInst.start.apply(gulpInst, toRun);
                                              ^

                                              TypeError: Cannot read property 'apply' of undefined
                                              at C:\Program Files\nodejs\node_modules\gulp\bin\gulp.js:129:20
                                              at process._tickCallback (internal/process/next_tick.js:61:11)
                                              at Function.Module.runMain (internal/modules/cjs/loader.js:745:11)
                                              at startup (internal/bootstrap/node.js:282:19)
                                              at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)

                                              Вроде бы делаю всё по инструкции. На что посмотреть и что поправить, чтобы gulp запустился как положено?
                                              1. Александр Мальцев
                                                24 июня 2019, 04:20
                                                Здравствуйте.
                                                Проверьте какая у вас версия gulp и nodejs.
                                                Версию Gulp можно узнать так:
                                                npm info gulp version
                                                
                                                Должна быть не ниже 4.0.0.
                                                Версию node.js можно проверить так:
                                                nodejs -v
                                                
                                                Необходимо иметь 10.x.x.
                                                1. Natalia
                                                  24 июня 2019, 05:11
                                                  С этим всё в порядке.
                                                  Gulp — 4.0.2.
                                                  Nodejs — 10.14.2.
                                                  1. Александр Мальцев
                                                    24 июня 2019, 07:53
                                                    Значит необходимо проверить установлен ли Gulp в папку с проектом. Для этого перейдите в командной строке в директорию проекта и введите команду:
                                                    gulp --version
                                                    
                                                    Если установлена только CLI версия, то запустите на установку gulp в ваш проект:
                                                    npm install gulp --save-dev
                                                    
                                                    Если это не поможет, то попробуйте выполнить следующие команды:
                                                    npm uninstall -g gulp
                                                    npm uninstall -g gulp-cli
                                                    
                                                    npm install -g gulp-cli
                                                    npm install gulp --save-dev
                                                    
                                                    Последнюю команду нужно запускать в командной строке, только после того как вы перешли в директорию своего проекта, т.е. из места в котором у вас расположен файл «gulpfile.js».
                                                    1. Natalia
                                                      24 июня 2019, 08:23
                                                      Сделала как предложено. Не помогло.
                                                      Та же ошибка выдается.
                                                      1. Александр Мальцев
                                                        26 июня 2019, 09:38
                                                        А вы берете с GitHub или сами все создаёте по описанию, представленному на этой странице?
                                                        1. Natalia
                                                          26 июня 2019, 20:43
                                                          Пробовала оба варианта — один и тот же результат.
                                              2. Александр
                                                17 июня 2019, 00:47
                                                Александр, а как сюда прикрутить babel для es6?
                                                1. Александр Мальцев
                                                  19 июня 2019, 12:05
                                                  Добавил в проект на Github новую ветку with babel.
                                                  В этой версии немного изменил логику. Теперь в папке "/src/js" два файла: «vendor.js» и «main.js». В «vendor.js» включаются сторонние библиотеки, а в «main.js» включаются свои js файлы.
                                                  Логика работы в этой ветки по сбору js файла такая: сначала собирается файл «main.js» из файлов, который затем обрабатывается с помощью babel; после этого собираются сторонние библиотеки из указанных файлов в «vendor.js»; оба этих собранных файла помещаются в папку "/build/js/cache/"; в конце оба этих файла объединяются в итоговый файл «all.js».

                                                  В качестве browserslist установлен defaults. Что обеспечивает поддержку следующих браузеров: > 0.5%, last 2 versions, Firefox ESR, not dead.
                                                2. Александр
                                                  30 мая 2019, 19:21
                                                  Добрый день. Отличная сборка. Спасибо. Подскажите, пож-та, а как сделать так чтобы собиралось 2 отдельных файла css. Один условно для главной страницы (main.css), а другой для оформления остальных. При этом 2-й файл также использует bootstrap, sass и минифицируется. Буду очень признателен за ответ.
                                                  1. Александр Мальцев
                                                    31 мая 2019, 13:41
                                                    Добрый!
                                                    Для этого создайте дополнительно main2.scss и укажите в нём что должно, например, участвовать в сборке для главной страницы.
                                                    Затем создайте дополнительную задачу, которая будет использоваться для подготовки CSS для главной страницы.
                                                    // сбор стилей
                                                    gulp.task('css2:build', function () {
                                                    return gulp.src('assets/src/style/main2.scss') // получим main2.scss

                                                    });
                                                    После этого добавьте его в другие задачи, где есть css:build:
                                                    // сборка
                                                    gulp.task('build', [
                                                      'clean:build',
                                                      'html:build',
                                                      'css:build',
                                                      'css2:build',
                                                      ...
                                                    
                                                    1. Александр
                                                      03 июня 2019, 00:18
                                                      Спасибо огромное. Вроде бы все получилось. Еще вопрос, по поводу прикрутки php. Да, видел похожий вопрос ниже, но мой немного отличается. Мне необходима работа с php wordpressa, нужно только чтобы отслеживались изменения в файлах php и перезагружался браузер. Т.е. перемещение в папку build не нужно. Ну и файлы php находятся в корне папки с темой, а не в src. Подскажите, плиз, какие изменения внести? Заранее признателен
                                                      1. Александр Мальцев
                                                        03 июня 2019, 16:54
                                                        Отлично!
                                                        Добавить задачу:
                                                        gulp.task('php:watch', function (done) {
                                                          webserver.reload();
                                                          done();
                                                        });
                                                        ...
                                                        // запуск задач при изменении файлов
                                                        gulp.task('watch', function () {
                                                          ...
                                                          // установить нужный путь...
                                                          gulp.watch('assets/src/**/*.php', gulp.series('php:watch'));
                                                        });
                                                        
                                                  2. fet
                                                    25 марта 2019, 19:28
                                                    Александр, было бы чудесно, если бы в эту сборку добавили PostCss, очень удобно было бы. Может реализуете?
                                                    1. Александр Мальцев
                                                      04 апреля 2019, 15:55
                                                      Пока планов таких нет. Если он вам нужен, можете его добавить самостоятельно.
                                                    2. cleantis
                                                      21 марта 2019, 11:37
                                                      Вот такую ошибку при запуске gulp выдает.
                                                      C:\Users\admin\Desktop\zp>gulp
                                                      internal/modules/cjs/loader.js:584
                                                      throw err;
                                                      ^

                                                      Error: Cannot find module 'imagemin-pngquant'
                                                      at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
                                                      at Function.Module._load (internal/modules/cjs/loader.js:508:25)
                                                      at Module.require (internal/modules/cjs/loader.js:637:17)
                                                      at require (internal/modules/cjs/helpers.js:22:18)
                                                      at Object.(C:\Users\admin\Desktop\zp\gulpfile.js:62:16)
                                                      at Module._compile (internal/modules/cjs/loader.js:701:30)
                                                      at Object.Module._extensions..js (internal/modules/cjs/loader.js:712:10)
                                                      at Module.load (internal/modules/cjs/loader.js:600:32)
                                                      at tryModuleLoad (internal/modules/cjs/loader.js:539:12)
                                                      at Function.Module._load (internal/modules/cjs/loader.js:531:3)

                                                      C:\Users\admin\Desktop\zp>
                                                      1. Александр Мальцев
                                                        21 марта 2019, 12:37
                                                        Необходимо учиться читать ошибки. Там же явно написано, что не найден модуль imagemin-pngquant.
                                                        1. cleantis
                                                          21 марта 2019, 12:44
                                                          да вроде грамотный, но к сожалению не ставится
                                                          C:\Users\admin\Desktop\zp>npm install imagemin-pngquant

                                                          > pngquant-bin@5.0.2 postinstall C:\Users\admin\Desktop\zp\node_modules\pngquant
                                                          -bin
                                                          > node lib/install.js

                                                          ‼ Command failed: C:\Users\admin\Desktop\zp\node_modules\pngquant-bin\vendor\p
                                                          ngquant.exe --version

                                                          ‼ pngquant pre-build test failed
                                                          i compiling from source
                                                          ? Error: pngquant failed to build, make sure that libpng-dev is installed
                                                          at Promise.all.then.arr (C:\Users\admin\Desktop\zp\node_modules\execa\index.
                                                          js:231:11)
                                                          at process._tickCallback (internal/process/next_tick.js:68:7)
                                                          npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules\fse
                                                          vents):
                                                          npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@
                                                          1.2.7: wanted {«os»:«darwin»,«arch»:«any»} (current: {«os»:«win32»,«arch»:«x64»}
                                                          )

                                                          npm ERR! code ELIFECYCLE
                                                          npm ERR! errno 1
                                                          npm ERR! pngquant-bin@5.0.2 postinstall: `node lib/install.js`
                                                          npm ERR! Exit status 1
                                                          npm ERR!
                                                          npm ERR! Failed at the pngquant-bin@5.0.2 postinstall script.
                                                          npm ERR! This is probably not a problem with npm. There is likely additional log
                                                          ging output above.

                                                          npm ERR! A complete log of this run can be found in:
                                                          npm ERR! C:\Users\admin\AppData\Roaming\npm-cache\_logs\2019-03-21T09_43_24_
                                                          116Z-debug.log

                                                          C:\Users\admin\Desktop\zp>
                                                          1. Александр Мальцев
                                                            21 марта 2019, 13:58
                                                            Он же приводит почему модуль «imagemin-pngquant» не может быть установлен. Это происходит из-за того, что установлен модуль libpng-dev (pngquant failed to build, make sure that libpng-dev is installed).
                                                      2. Вячеслав
                                                        10 марта 2019, 22:50
                                                        Первая статья, в которой все написано понятно, и ВСЕ РАБОТАЕТ. Вот только не понял, а зачем устанавливать Bootstrap, Jquery и Popper.js дважды — через npm и через Bower?
                                                        1. Александр Мальцев
                                                          11 марта 2019, 13:44
                                                          Нет, Bower сейчас использовать не нужно. Сейчас все пакеты устанавливаются через npm. Он остался в статье для совместимости (для пользователей), которую используют ещё первую версию данной сборки.
                                                        2. Михаил
                                                          02 марта 2019, 17:02
                                                          Александр Мальцев, ты лучший. Скачал архив, написал «npm i» и всё работает!
                                                          1. Михаил
                                                            02 марта 2019, 18:13
                                                            Только единственное, что не могу понять, у меня не запускается автоперезагрузка сервера при изменениях css и scss файлов, приходится вручную страницу обновлять, хотя если вносить изменения в html то сервер сам перезагружается, Александр, подскажите, в чём может быть дело?
                                                            1. Александр Мальцев
                                                              03 марта 2019, 06:25
                                                              Спасибо за отзыв. Исправил этот недочёт и некоторые другие. В статье обновил ссылку на архив.
                                                              Чтобы это исправить можешь либо обновить файлы в своём проекте, либо самостоятельно внести изменения в файл head.html (указать ссылку на минимизированный файл стилей):
                                                              <link rel="stylesheet" href="css/main.min.css">
                                                              
                                                              1. Михаил
                                                                03 марта 2019, 11:34
                                                                Изменил ссылку на минимизированный файл стилей, теперь всё обновляется в реальном времени, ты лучший, спасибо.
                                                          2. Dmitry
                                                            02 марта 2019, 03:58
                                                            Возникли проблемы с плагинами для сжатия картинок: «imagemin-pngquant» и «gulp-imagemin»
                                                            при установке выдают ошибку:
                                                            "… npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

                                                            npm WARN notsup SKIPPING OPTIONAL DEPENDENCY:
                                                            Unsupported platform for fsevents@1.2.4:

                                                            wanted {«os»:«darwin»,«arch»:«any»}
                                                            (current: {«os»:«win32»,«arch»:«ia32»})..."

                                                            Видимо, не поддерживают win7. Вы не встречали решения для этой проблемы?
                                                            1. Александр Мальцев
                                                              02 марта 2019, 05:21
                                                              В сообщение выдаётся предупреждение о том, что было пропущено установка необязательной зависимости «fsevents@1.2.4», т.к. она работает только на macOS.

                                                              Если есть проблема с плагинами «imagemin-pngquant» и «gulp-imagemin», то попробуйте обновить «Node.js» до последней версии из ветки «10.x.x».

                                                              После этого удалите папку с npm пакетами и попробуйте их установить заново с опцией "--no-option", т.е. без установки дополнительных зависимостей:
                                                              npm install --no-option
                                                              Если это не поможет, то попробуйте поискать другие плагины для обработки картинок (может это связано с архитектурой вашей ОС).
                                                            2. Dmitry
                                                              02 марта 2019, 03:50
                                                              Очень полезная статья, спасибо большое!
                                                              1. KL
                                                                11 января 2019, 14:52
                                                                Спасибо за подробную инструкцию!
                                                                Делаю следующие шаги:
                                                                1. git clone github.com/itchief/gulp-project-bootstrap-4.git
                                                                2. npm install
                                                                3. gulp

                                                                Получаю ошибки:
                                                                [14:50:28] 'webserver' errored after 158 ms
                                                                [14:50:28] Error: listen EPERM :::3000
                                                                    at Object._errnoException (util.js:992:11)
                                                                    at _exceptionWithHostPort (util.js:1014:20)
                                                                    at Server.setupListenHandle [as _listen2] (net.js:1355:14)
                                                                    at listenInCluster (net.js:1396:12)
                                                                    at Server.listen (net.js:1480:7)
                                                                    at module.exports.plugin (/public_html/node_modules/
                                                                browser-sync/dist/server/index.js:27:25)
                                                                    at Object.startServer [as fn] (/public_html/node_mod
                                                                ules/browser-sync/dist/async.js:177:52)
                                                                    at /public_html/node_modules/browser-sync/dist/brows
                                                                er-sync.js:120:14
                                                                    at iterate (/public_html/node_modules/browser-sync/d
                                                                ist/utils.js:269:9)
                                                                    at /public_html/node_modules/browser-sync/dist/utils
                                                                .js:281:21
                                                                [14:50:28] 'default' errored after 5.73 s
                                                                [14:50:28] The following tasks did not complete: watch
                                                                [14:50:28] Did you forget to signal async completion?
                                                                Что делаю не так?)
                                                                1. Александр Мальцев
                                                                  11 января 2019, 15:36
                                                                  Node.js должна быть не ниже 10.x
                                                                  1. KL
                                                                    11 января 2019, 15:55
                                                                    Обновил до:
                                                                    node 10.15.0
                                                                    npm 6.4.1

                                                                    Сделал всё заново, теперь чуть другие ошибки:

                                                                    [15:52:07] 'webserver' errored after 207 ms
                                                                    [15:52:07] Error: listen EPERM: operation not permitted :::3000
                                                                        at Server.setupListenHandle [as _listen2] (net.js:1290:14)
                                                                        at listenInCluster (net.js:1338:12)
                                                                        at Server.listen (net.js:1425:7)
                                                                        at module.exports.plugin (/public_html/node_modules/
                                                                    browser-sync/dist/server/index.js:27:25)
                                                                        at Object.startServer [as fn] (/public_html/node_mod
                                                                    ules/browser-sync/dist/async.js:177:52)
                                                                        at /public_html/node_modules/browser-sync/dist/brows
                                                                    er-sync.js:120:14
                                                                        at iterate (/public_html/node_modules/browser-sync/d
                                                                    ist/utils.js:269:9)
                                                                        at /public_html/node_modules/browser-sync/dist/utils
                                                                    .js:281:21
                                                                        at executeTask (/public_html/node_modules/browser-sy
                                                                    nc/dist/browser-sync.js:136:13)
                                                                        at Object.mergeMiddlewares [as fn] (/public_html/nod
                                                                    e_modules/browser-sync/dist/async.js:166:9)
                                                                    [15:52:07] 'default' errored after 5.85 s
                                                                    [15:52:07] The following tasks did not complete: watch
                                                                    [15:52:07] Did you forget to signal async completion?
                                                                    
                                                                    1. Александр Мальцев
                                                                      12 января 2019, 06:21
                                                                      Какая ОС? А также версия gulp (gulp -v)?
                                                                  2. Александр Мальцев
                                                                    11 января 2019, 15:14
                                                                    Пожалуйста! Node.js (nodejs -v) и npm (npm -v) какой версии?
                                                                  3. fet
                                                                    05 января 2019, 12:46
                                                                    Александр спасибо, очень приятная сборка, сплошное удовольствие работать, если не затруднит подскажите как все это связать не SASS, а с PostCSS? это надо наверно целую статью переписывать (, может хотя бы примерно укажите направление, что бы понимать куда копать и возможно ли это, bootstrap 4 засунуть в PostCSS? Если бы написали развернуто ) был бы премного благодарен.
                                                                    1. Александр Мальцев
                                                                      05 января 2019, 15:08
                                                                      Тут, скорее всего, придётся делать двойную связку. Bootstrap 4 написан на SASS, и от этого не куда не деться. Т.е. исходные стили Bootstrap 4 в css компилируете с помощью gulp-sass, а свои в css — с помощью gulp-postcss. После этого полученные промежуточные css файлы объединяете, например, с помощью gulp-concat-css.
                                                                    2. Андрей
                                                                      02 января 2019, 21:56
                                                                      Александр, подскажите, в какой файл нужно добавлять свои брекпойнты? Добавил в свой variables.scss такой массив, но почему-то огни не добавились после компиляции.
                                                                      $grid-breakpoints: (
                                                                          xxs: 0,
                                                                          xs: 375px;
                                                                          sm: 576px,
                                                                          md: 768px,
                                                                          lg: 992px,
                                                                          xl: 1200px
                                                                      );
                                                                      
                                                                      $container-max-widths (
                                                                        (
                                                                          xs: 375px,
                                                                          sm: 540px,
                                                                          md: 720px,
                                                                          lg: 960px,
                                                                          xl: 1140px
                                                                        )
                                                                      );
                                                                      1. Александр Мальцев
                                                                        04 января 2019, 14:43
                                                                        Новые брекпойнты можно добавлять только в конец списка.
                                                                        $grid-breakpoints: (
                                                                            xs: 0,
                                                                            sm: 375px,
                                                                            md: 576px,
                                                                            lg: 768px,
                                                                            xl: 992px,
                                                                            vl: 1200px
                                                                        );
                                                                        $container-max-widths: (
                                                                            sm: 375px,
                                                                            md: 540px,
                                                                            lg: 720px,
                                                                            xl: 960px,
                                                                            vl: 1140px
                                                                        );
                                                                        
                                                                        1. Андрей
                                                                          08 января 2019, 12:37
                                                                          Спасибо, понял)
                                                                      2. Nubbie
                                                                        17 декабря 2018, 14:46
                                                                        Здравствуйте, мануал устарел и с актуальным Gulp4 не работает -(
                                                                        1. Александр Мальцев
                                                                          19 декабря 2018, 17:24
                                                                          Здравствуйте. Файл gulpfile.js обновлён до Gulp 4. Окружение можно загрузить с github. Статья по настройке окружения будет обновлена в ближайшее время.
                                                                        2. Dmitry
                                                                          09 ноября 2018, 16:34
                                                                          Здравствуйте
                                                                          Как php прикрутить к Вашей сборке? Файл php из папки src ни в какую не хочет перемещаться в папку build, прописывал в файле gulpfile.js php по аналогу html
                                                                          Спасибо!
                                                                          У Вас тут столько интересного связанного с php)
                                                                          1. Александр Мальцев
                                                                            10 ноября 2018, 16:35
                                                                            Здравствуйте, спасибо!
                                                                            Для этого достаточно внести следующие изменения в gulpfile.js:
                                                                            var path = {
                                                                              ...
                                                                              src: {
                                                                                html:  ['assets/src/*.html','assets/src/*.php'],
                                                                                ...
                                                                              },
                                                                              watch: {
                                                                                html:  ['assets/src/**/*.html','assets/src/**/*.php'],
                                                                                ...
                                                                            };
                                                                            
                                                                            1. Dmitry
                                                                              11 ноября 2018, 13:20
                                                                              Здравствуйте Александр!
                                                                              Большое спасибо за ответ, помогло, файлы php и .htaccess переносятся из папки src в папку build. Как теперь связать галп с опен сервером для работы с php, не знаю, в интернете много советов но они как то не подходят. если не трудно подскажите пожалуйста.

                                                                              И еще, хочу попробовать поставить вашу форму обратной связи itchief.ru/bootstrap/feedback-form, папку feedback загрузил в папку src она тоже переносится в папку build, но уже немного легче, может ее как то надо загружать в в папку node modules?

                                                                              Спасибо!!!
                                                                              1. Александр Мальцев
                                                                                11 ноября 2018, 14:11
                                                                                Можно так (на примере домена localhost):
                                                                                1. Изменить настройки сервера browser-sync:
                                                                                /* настройки сервера */
                                                                                var config = {
                                                                                    /*server: {
                                                                                        baseDir: './assets/build'
                                                                                    },*/
                                                                                    proxy: "localhost",
                                                                                    notify: false
                                                                                };
                                                                                
                                                                                2. В настройках Open Server Panel на вкладке домены для localhost указать в качестве папки домена место, где находится build (например, \localhost\assets\build).

                                                                                Папку feedback загружайте в src, она не является npm пакетом.
                                                                                1. Dmitry
                                                                                  11 ноября 2018, 23:42
                                                                                  Спасибо!!! с пхп получилось
                                                                          2. Dmitry
                                                                            08 ноября 2018, 20:15
                                                                            Здравствуйте
                                                                            Использую Вашу сборку, такой вопрос, делаю многостраничный сайт. Как сделать так, чтобы скрипты и стили загружались только на той странице сайта на которой используются. Например, под фотогалерею отведена отдельная страница, зачем все скрипты от нее таскать по всему сайту, если они нужны только на одной. Наверное это трудно сделать так? Спасибо!!!
                                                                            1. Александр Мальцев
                                                                              09 ноября 2018, 15:44
                                                                              Здравствуйте! Обычно такую задачу решают с помощью RequireJS.
                                                                              1. Dmitry
                                                                                09 ноября 2018, 16:48
                                                                                Спасибо! буду пробовать, разбираться)
                                                                            2. Denis
                                                                              08 сентября 2018, 17:23
                                                                              Добрый день!
                                                                              Я использую Вашу сборку Gulp. Подскажите, что необходимо прописать в gulpfile.js?
                                                                              Задача: При сборке проекта перенести "папка, с разными файлами разных расширений" из папки "src" со всем её содержимым в папку "build".
                                                                              Можно без всяких сжатий, как есть 100%.

                                                                              За ранее спасибо за ответ.
                                                                              1. Александр Мальцев
                                                                                09 сентября 2018, 14:34
                                                                                Добрый! Сделайте по аналогии с задачей (task), которая используется для переноса шрифтов.
                                                                              2. Denis
                                                                                30 августа 2018, 09:58
                                                                                Добрый день!
                                                                                Подскажите, как правильно добавить в Вашу сборку Gulp -> Vue.js + Vuetify?

                                                                                За ранее спасибо за ответ.

                                                                                1. Egor
                                                                                  24 августа 2018, 06:54
                                                                                  Александр, добрый день!
                                                                                  Подскажите, чем можно заменить команду «gulp.start». Не работает на gulp 4.0.0
                                                                                  Фрагмент кода ниже.
                                                                                  Спасибо.

                                                                                  gulp.task('build:frontend', function () {
                                                                                    gulp.start(
                                                                                      'build:frontend:assets:copy-images-vendors',
                                                                                      'build:frontend:assets:copy-js-vendors',
                                                                                      'build:frontend:assets:copy-photoswipe-css-and-images',
                                                                                      'build:frontend:sass:generate-css',
                                                                                      'build:frontend:sass:generate-module-css'
                                                                                    )
                                                                                  })
                                                                                  
                                                                                  1. Egor
                                                                                    24 августа 2018, 06:46
                                                                                    Доброго времени суток!
                                                                                    Александр, если возможно, подскажите, как можно заменить команду «gulp.start» в нижеприведенном коде. Проблема в том, что «gulp.start» выпилили в gulp 4.0.0 и скрипт больше не исполняется. Скрипт написан не мной и прекрасно работает на gulp 3.9.1 но не на gulp 4.0.0. К сожалению к разработчику обратиться не могу, так как его «все устраивает».

                                                                                    Спасибо.

                                                                                    /* jslint node: true */
                                                                                    'use strict';
                                                                                    
                                                                                    const gulp = require('gulp')
                                                                                    const sass = require('gulp-sass')
                                                                                    const sourcemaps = require('gulp-sourcemaps')
                                                                                    const autoprefixer = require('gulp-autoprefixer')
                                                                                    const rename = require('gulp-rename')
                                                                                    const livereload = require('gulp-livereload')
                                                                                    
                                                                                    // backend tasks
                                                                                    gulp.task('build:backend:assets:copy-css-vendors', function () {
                                                                                      return gulp.src([
                                                                                        'node_modules/bootstrap-tagsinput/dist/bootstrap-tagsinput.css',
                                                                                        'node_modules/bootstrap-tagsinput/dist/bootstrap-tagsinput-typeahead.css',
                                                                                        'node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.standalone.min.css',
                                                                                        'node_modules/cropper/dist/cropper.css',
                                                                                        'node_modules/bootstrap-accessibility-plugin/plugins/css/bootstrap-accessibility.css'
                                                                                      ])
                                                                                      .pipe(gulp.dest('./css/vendors'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:backend:assets:copy-fonts-vendors', function () {
                                                                                      return gulp.src([
                                                                                        'node_modules/font-awesome/fonts/**'
                                                                                      ])
                                                                                      .pipe(gulp.dest('fonts/vendors'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:backend:assets:copy-ckeditor', function () {
                                                                                      var pluginFiles = '/**/*.@(js|png|jpg|jpeg|gif|css|html|svg)'
                                                                                      return gulp.src(
                                                                                        [
                                                                                          'node_modules/ckeditor/adapters/*.js',
                                                                                          'node_modules/ckeditor/lang/*.js',
                                                                                          'node_modules/ckeditor/plugins/icons.png',
                                                                                          'node_modules/ckeditor/plugins/icons_hidpi.png',
                                                                                          'node_modules/ckeditor/plugins/clipboard' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/codemirror' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/colordialog' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/copyformatting' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/dialog' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/dialogadvtab' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/div' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/docprops' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/iframe' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/iframe' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/image' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/link' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/liststyle' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/pastefromword' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/specialchar' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/table' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/tabletools' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/stylesheetparser' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/templates' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/uicolor' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/widget' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/wsc' + pluginFiles,
                                                                                          'node_modules/ckeditor/plugins/lineutils' + pluginFiles,
                                                                                          'node_modules/ckeditor/skins/moono-lisa/**/*.@(css|png|gif)',
                                                                                          'node_modules/ckeditor/ckeditor.js',
                                                                                          'node_modules/ckeditor/contents.css',
                                                                                          'node_modules/ckeditor/styles.js',
                                                                                          'node_modules/ckeditor/LICENSE.md'
                                                                                        ],
                                                                                        {base: 'node_modules/ckeditor'}
                                                                                      ).pipe(gulp.dest('src/Backend/Core/Js/ckeditor'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:backend:assets:copy-fine-uploader-css-and-images', function () {
                                                                                      return gulp.src([
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/fine-uploader-new.min.css',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/continue.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/edit.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/loading.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/pause.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/processing.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/retry.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/trash.gif',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/placeholders/waiting-generic.png',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/placeholders/not_available-generic.png'
                                                                                      ])
                                                                                      .pipe(gulp.dest('./css/vendors/fine-uploader'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:backend:assets:copy-js-vendors', function () {
                                                                                      return gulp.src([
                                                                                        'node_modules/jquery/dist/jquery.min.js',
                                                                                        'node_modules/jquery-migrate/dist/jquery-migrate.min.js',
                                                                                        'node_modules/jquery-ui-dist/jquery-ui.min.js',
                                                                                        'node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js',
                                                                                        'node_modules/bootstrap-tagsinput/dist/bootstrap-tagsinput.min.js',
                                                                                        'node_modules/fine-uploader/jquery.fine-uploader/jquery.fine-uploader.min.js',
                                                                                        'node_modules/simple-ajax-uploader/SimpleAjaxUploader.min.js',
                                                                                        'node_modules/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js',
                                                                                        'node_modules/cropper/dist/cropper.js',
                                                                                        'node_modules/bootstrap-accessibility-plugin/plugins/js/bootstrap-accessibility.min.js'
                                                                                      ])
                                                                                      .pipe(gulp.dest('js/vendors'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:backend:sass:generate-css', function () {
                                                                                      return gulp.src([
                                                                                        'src/Backend/Core/Layout/Sass/screen.scss',
                                                                                        'src/Backend/Core/Layout/Sass/debug.scss'
                                                                                      ])
                                                                                      .pipe(sourcemaps.init())
                                                                                      .pipe(sass({
                                                                                        includePaths: [
                                                                                          'node_modules/'
                                                                                        ],
                                                                                        outputStyle: 'compressed',
                                                                                        precision: 10
                                                                                      }))
                                                                                      .pipe(autoprefixer({}))
                                                                                      .pipe(sourcemaps.write('./', {
                                                                                        includeContent: false,
                                                                                        sourceRoot: 'src/Backend/Core/Layout/Sass'
                                                                                      }))
                                                                                      .pipe(gulp.dest('src/Backend/Core/Layout/Css'))
                                                                                      .pipe(livereload())
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:backend', function () {
                                                                                      gulp.start(
                                                                                        'build:backend:assets:copy-css-vendors',
                                                                                        'build:backend:assets:copy-fonts-vendors',
                                                                                        'build:backend:assets:copy-js-vendors',
                                                                                        'build:backend:assets:copy-fine-uploader-css-and-images',
                                                                                        'build:backend:sass:generate-css',
                                                                                        'build:backend:assets:copy-ckeditor'
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    gulp.task('serve:backend', function () {
                                                                                      livereload.listen()
                                                                                      gulp.watch(
                                                                                        [
                                                                                          'src/Backend/Core/Layout/Sass/**/*.scss'
                                                                                        ],
                                                                                        ['build:backend:sass:generate-css']
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    // frontend tasks
                                                                                    gulp.task('build:frontend:assets:copy-images-vendors', function () {
                                                                                      var components = {
                                                                                      }
                                                                                    
                                                                                      for (var key in components) {
                                                                                        return gulp.src(components[key]).pipe(gulp.dest('./images/vendors/' + key))
                                                                                      }
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:frontend:assets:copy-js-vendors', function () {
                                                                                      return gulp.src([
                                                                                        'node_modules/photoswipe/dist/photoswipe.min.js',
                                                                                        'node_modules/photoswipe/dist/photoswipe-ui-default.min.js',
                                                                                        'node_modules/slick-carousel/slick/slick.min.js'
                                                                                      ])
                                                                                      .pipe(gulp.dest('js/vendors'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:frontend:assets:copy-photoswipe-css-and-images', function () {
                                                                                      return gulp.src([
                                                                                        'node_modules/photoswipe/dist/photoswipe.css',
                                                                                        'node_modules/photoswipe/dist/default-skin/*.{png,svg,gif,jpg,css}'
                                                                                      ])
                                                                                        .pipe(gulp.dest('css/vendors/photoswipe'))
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:frontend:sass:generate-css', function () {
                                                                                      return gulp.src([
                                                                                        'src/Frontend/Core/Layout/Sass/debug.scss',
                                                                                        'src/Frontend/Core/Layout/Sass/editor_content.scss',
                                                                                        'src/Frontend/Core/Layout/Sass/screen.scss'
                                                                                      ])
                                                                                      .pipe(sourcemaps.init())
                                                                                      .pipe(sass({
                                                                                        includePaths: [
                                                                                          'node_modules/'
                                                                                        ],
                                                                                        outputStyle: 'compressed',
                                                                                        precision: 10
                                                                                      }))
                                                                                      .pipe(autoprefixer({}))
                                                                                      .pipe(sourcemaps.write('./', {
                                                                                        includeContent: false,
                                                                                        sourceRoot: 'src/Frontend/Core/Layout/Sass'
                                                                                      }))
                                                                                      .pipe(gulp.dest('src/Frontend/Core/Layout/Css'))
                                                                                      .pipe(livereload())
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:frontend:sass:generate-module-css', function () {
                                                                                      return gulp.src([
                                                                                        'src/Frontend/Modules/**/Layout/Sass/*.scss'
                                                                                      ])
                                                                                      .pipe(sass({
                                                                                        includePaths: [
                                                                                          'node_modules/'
                                                                                        ],
                                                                                        outputStyle: 'compressed',
                                                                                        precision: 10
                                                                                      }))
                                                                                      .pipe(autoprefixer({}))
                                                                                      .pipe(rename(function (path) {
                                                                                        path.dirname = path.dirname.replace('/Sass', '/Css')
                                                                                      }))
                                                                                      .pipe(gulp.dest('src/Frontend/Modules/'))
                                                                                      .pipe(livereload())
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:frontend', function () {
                                                                                      gulp.start(
                                                                                        'build:frontend:assets:copy-images-vendors',
                                                                                        'build:frontend:assets:copy-js-vendors',
                                                                                        'build:frontend:assets:copy-photoswipe-css-and-images',
                                                                                        'build:frontend:sass:generate-css',
                                                                                        'build:frontend:sass:generate-module-css'
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    gulp.task('serve:frontend', function () {
                                                                                      livereload.listen()
                                                                                      gulp.watch(
                                                                                        [
                                                                                          'src/Frontend/Modules/**/Layout/Sass/*.scss'
                                                                                        ],
                                                                                        ['build:frontend:sass:generate-module-css']
                                                                                      )
                                                                                      gulp.watch(
                                                                                        [
                                                                                          'src/Frontend/Core/Layout/Sass/debug.scss',
                                                                                          'src/Frontend/Core/Layout/Sass/editor_content.scss',
                                                                                          'src/Frontend/Core/Layout/Sass/screen.scss'
                                                                                        ],
                                                                                        ['build:frontend:sass:generate-css']
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    // Fork-theme tasks
                                                                                    gulp.task('build:theme-fork:sass:generate-css', function () {
                                                                                      return gulp.src([
                                                                                        'src/Frontend/Themes/Fork/Core/Layout/Sass/screen.scss'
                                                                                      ])
                                                                                      .pipe(sourcemaps.init())
                                                                                      .pipe(sass({
                                                                                        includePaths: [
                                                                                          'node_modules/'
                                                                                        ],
                                                                                        outputStyle: 'compressed',
                                                                                        precision: 10
                                                                                      }))
                                                                                      .pipe(autoprefixer({}))
                                                                                      .pipe(sourcemaps.write('./', {
                                                                                        includeContent: false,
                                                                                        sourceRoot: 'src/Frontend/Themes/Fork/Core/Layout/Sass'
                                                                                      }))
                                                                                      .pipe(gulp.dest('src/Frontend/Themes/Fork/Core/Layout/Css'))
                                                                                      .pipe(livereload())
                                                                                    })
                                                                                    
                                                                                    gulp.task('build:theme-fork', function () {
                                                                                      gulp.start(
                                                                                        'build:theme-fork:sass:generate-css'
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    gulp.task('serve:theme-fork', function () {
                                                                                      livereload.listen()
                                                                                      gulp.watch(
                                                                                        [
                                                                                          'src/Frontend/Themes/Fork/Core/Layout/Sass/**/*.scss'
                                                                                        ],
                                                                                        ['build:theme-fork:sass:generate-css']
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    // public tasks
                                                                                    gulp.task('default', function () {
                                                                                      gulp.start('build')
                                                                                    })
                                                                                    
                                                                                    gulp.task('serve', function () {
                                                                                      gulp.start(
                                                                                        'serve:backend',
                                                                                        'serve:frontend',
                                                                                        'serve:theme-fork'
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    gulp.task('build', function () {
                                                                                      gulp.start(
                                                                                        'build:backend',
                                                                                        'build:frontend',
                                                                                        'build:theme-fork'
                                                                                      )
                                                                                    })
                                                                                    
                                                                                    
                                                                                    1. Denis
                                                                                      12 августа 2018, 08:49
                                                                                      Добрый день!
                                                                                      Подскажите, как правильно добавлять плагины в сборке (например: «Owl Carousel 2»)?
                                                                                      Подскажите, как обновлять плагины в файле «package.json» до новой версии?

                                                                                      За ранее спасибо за ответ.
                                                                                      1. Александр Мальцев
                                                                                        13 августа 2018, 14:31
                                                                                        Добрый!
                                                                                        Подключить плагин Owl Carousel 2 можно, например, так:
                                                                                        1. Открыть файл package.json и добавить название пакета owl.carousel в секцию dependencies:
                                                                                        "dependencies": {
                                                                                          "jquery": "^3.3.1",
                                                                                          "popper.js": "^1.14.4",
                                                                                          "bootstrap": "^4.1.3",
                                                                                          "owl.carousel": "^2.3.4"
                                                                                        }
                                                                                        
                                                                                        2. Ввести команду:
                                                                                        npm install
                                                                                        
                                                                                        Другой вариант — это просто ввести команду:
                                                                                        npm add owl.carousel
                                                                                        
                                                                                        После установки плагина Owl Carousel 2, его необходимо подключить к проекту:
                                                                                        1. Открываем main.js и вставляем в него следующее:
                                                                                        // Импортируем JavaScript Owl Carousel 2
                                                                                        //= ../../../node_modules/owl.carousel/dist/owl.carousel.js
                                                                                        
                                                                                        2. Открываем main.scss и вставляем в него следующий код:
                                                                                        // Подключение CSS Owl Carousel 2
                                                                                        @import "../../../node_modules/owl.carousel/dist/assets/owl.carousel.css";
                                                                                        Для обновления пакетов необходимо ввести команду:
                                                                                        npm update
                                                                                        
                                                                                        Узнать версию пакета (например, owl.carousel) можно так:
                                                                                        npm view owl.carousel version
                                                                                        
                                                                                        1. Denis
                                                                                          13 августа 2018, 15:56
                                                                                          Супер, большое спасибо за качественный развернутый ответ.
                                                                                      2. Егор
                                                                                        04 августа 2018, 09:06
                                                                                        Здравствуйте. Я компилирую программой Koala, но вопрос другой: можно ли используя Bootstrap SCSS исключить классы warning, danger и другие, ведь в проекте используется всего 2-3 цвета, плюс цвета типографии? Например нужно оставить default и primary, а остальное связанное с другими классами исключить.
                                                                                        1. Александр Мальцев
                                                                                          04 августа 2018, 12:30
                                                                                          Здравствуйте. Да их можно убрать. Для этого нужно в файле _variables.scss найти строчку со списком тем и оставить только нужные:
                                                                                          $theme-colors: map-merge(
                                                                                            (
                                                                                              "primary":    $primary,
                                                                                              "success":    $success,
                                                                                              "danger":     $danger
                                                                                            ),
                                                                                            $theme-colors
                                                                                          );
                                                                                          
                                                                                          В Bootstrap 4 темы default нет, а темы primary, success и danger используется в компонентах. Тема primary используется для стилизации ссылок, progress и др. Темы success и danger в формах. Поэтому их лучше оставить и назначить им необходимые цвета.
                                                                                          1. Егор
                                                                                            04 августа 2018, 14:23
                                                                                            Спасибо, получилось. success и danger попробовал ради эксперимента убрать, компилятор ошибку выдает и пишет, где еще используются эти переменные.
                                                                                        2. Denis
                                                                                          14 июля 2018, 21:58
                                                                                          Добрый день!
                                                                                          Подскажите, что можно исправить? При запуске gulp выводит ошибку:
                                                                                          buffer.js:207
                                                                                              throw new ERR_INVALID_ARG_TYPE(
                                                                                              ^
                                                                                          
                                                                                          TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type undefined
                                                                                              at Function.from (buffer.js:207:11)
                                                                                              at new Buffer (buffer.js:182:17)
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\gulp-rigger\index.js:20:29
                                                                                              at Rigger.<anonymous> (D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\index.js:719:9)
                                                                                              at Rigger.emit (events.js:182:13)
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\index.js:252:16
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:232:13
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:113:21
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:24:16
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:229:17
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\index.js:391:21
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\index.js:167:7
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:232:13
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:113:21
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:24:16
                                                                                              at D:\Home_Station\W_M_s\Open_Server\OSPanel\domains\project_220405\node_modules\rigger\node_modules\async\lib\async.js:229:17
                                                                                          
                                                                                          Большое спасибо за ответ. Я только начал осваивать gulp.
                                                                                          1. Александр Мальцев
                                                                                            15 июля 2018, 15:05
                                                                                            Тут два варианта. Либо разбираться с исключением, которое выбрасывает buffer.js в связи с тем, что передаётся неправильный тип аргумента. Либо просто создать сначала пустой проект, проверить его работу. Если всё хорошо, то последовательно подключать к файлам main.scss и main.js исходные файлы SCSS и JS.
                                                                                            1. Denis
                                                                                              15 июля 2018, 21:41
                                                                                              Добрый день!
                                                                                              А можете подсказать как подключить плагин rigger (что прописать в gulpfile), у меня есть рабочий проект с подключенными плагинами, но с rigger не получается. Не подключаются файлы.
                                                                                              Большое спасибо за ответ.
                                                                                              1. Александр Мальцев
                                                                                                16 июля 2018, 15:32
                                                                                                В статье есть информация как это сделать. Попробуйте сделать всё по этой инструкции. На гитхабе есть готовый проект, можете взять его.
                                                                                                1. Denis
                                                                                                  20 июля 2018, 09:59
                                                                                                  Добрый день!
                                                                                                  Эта ошибка, как раз и возникает при использовании готового проекта с гитхаба. После развертывания командой npm i и запуска команды gulp
                                                                                                  1. Александр Мальцев
                                                                                                    21 июля 2018, 08:01
                                                                                                    Добрый! Там кроме npm, нужно ещё и Bower зависимости установить. Он пытается собрать build из файлов, которых просто нет в каталоге bower_components.

                                                                                                    Но Bower является уже устаревшим пакетным менеджером. В новой версии проекта (2.0.0) Bower убран, теперь все зависимости устанавливаются с помощью npm. Также были обновлены версии зависимостей. Так что можете использовать новую версию.

                                                                                                    Если нужна старая версия с Bower (1.0.0), то её можно загрузить отсюда.
                                                                                                    1. Denis
                                                                                                      22 июля 2018, 05:47
                                                                                                      Супер! Огромное спасибо! Все работает.
                                                                                          2. andrey
                                                                                            21 мая 2018, 11:52
                                                                                            Добрый день.

                                                                                            И что дальше, продолжите урок дальше разверните, чтобы был опыт использования на каком нибудь хотя бы тестовом проекте, чтобы закрепить навыки, а то ни о чем получается…
                                                                                            1. Александр Мальцев
                                                                                              21 мая 2018, 13:43
                                                                                              Добрый! Продолжение будет (на примере создания лендинга).
                                                                                            2. Alexey
                                                                                              23 декабря 2017, 17:14
                                                                                              Добрый день!
                                                                                              Подскажите, в как установить gulp + modx на реальный удаленный сервер, чтобы при редактировании скриптов и стилей данные автоматически обновлялись на сервере и на экране соответственно. Ну, типа, FTP — тоннель
                                                                                              Спасибо!
                                                                                              1. Константин
                                                                                                18 декабря 2017, 00:46
                                                                                                Помогите решить эту проблему не могу понять почему rigger так себя ведет. Делал все по аналогии.
                                                                                                Не получилось запустить проект, выдает ошибку в консоле:

                                                                                                buffer.js:199
                                                                                                    throw new errors.TypeError(
                                                                                                    ^
                                                                                                
                                                                                                TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type undefined
                                                                                                    at Function.from (buffer.js:199:11)
                                                                                                    at new Buffer (buffer.js:174:17)
                                                                                                    at D:\newProjects\kos.tst\node_modules\gulp-rigger\index.js:20:29
                                                                                                    at Rigger.<anonymous> (D:\newProjects\kos.tst\node_modules\rigger\index.js:719:9)
                                                                                                    at Rigger.emit (events.js:159:13)
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\index.js:252:16
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:232:13
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:113:21
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:24:16
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:229:17
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\index.js:391:21
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\index.js:167:7
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:232:13
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:113:21
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:24:16
                                                                                                    at D:\newProjects\kos.tst\node_modules\rigger\node_modules\async\lib\async.js:229:17
                                                                                                
                                                                                                1. Александр Мальцев
                                                                                                  18 декабря 2017, 03:03
                                                                                                  Тут вам нужно проверять файлы, содержимое которых формируется с помощью rigger (в этой статье такими файлами являются index.html и main.js).

                                                                                                  Выполнить это можно, например, посредством исключения файлов. Кроме этого обратите внимание на то, чтобы путь не содержал пробелы и также чтобы их не было в конце конструкции //=.
                                                                                                2. Алексей
                                                                                                  23 ноября 2017, 14:36
                                                                                                  Благодарю за статью — даже с опытом написания сайтов в DreamWeaver и немного поработав с пре-процессорами, что-то понял))

                                                                                                  Дошел до запуска gulp, и последняя строчка была такой:
                                                                                                  [16:24:01] Plumber found unhandled error:
                                                                                                   Error in plugin 'gulp-sass'
                                                                                                  
                                                                                                  И, как совсем новичку в программировании, хотелось бы небольшую статью пример, как весь этот проект использовать — создать простенькую страничку и подгрузить к ней header и footer из каталога templates (очень интересна эта возможность)
                                                                                                  1. Александр Мальцев
                                                                                                    23 ноября 2017, 15:08
                                                                                                    Спасибо. Это сообщение «говорит» что у вас ошибка в стилях SСSS.
                                                                                                    Хорошо, сделаю статью, в которой опишу, как этот функционал использовать для создания веб-проекта.
                                                                                                    1. Алексей
                                                                                                      23 ноября 2017, 16:35
                                                                                                      Так вообще ничего пока не делал — просто систему пытаюсь настроить. Стилей пока нет никаких
                                                                                                      1. Александр Мальцев
                                                                                                        24 ноября 2017, 15:11
                                                                                                        Тогда проверьте существования файлов, которые вы указали в main.scss.
                                                                                                  2. Евгений
                                                                                                    17 ноября 2017, 16:21
                                                                                                    Александр, подскажите пожалуйста новичку:
                                                                                                    a) зачем нам пакетный менеджер bower (и прицепом git) если у нас уже есть нодовский пакетный менеджер npm? В статье вы при помощи bower ставите bootstrap, но ведь bootstrap можно поставить и через npm? Я так понимаю для гальпа то все равно? Кстати с официального сайта бутстрапа в разделе установка исчезла строчка про bower…
                                                                                                    b) огромная куча пакетов, что вы ставите c префиксом gulp- (обработка изображений, сжатия) вы их используете для сборки всего сайта, правильно? Бутсрапа здесь касается только gulp-sass и gulp-autoprefixer судя по официальной документации бутстрапа?
                                                                                                    c) Чтобы переопределить стили бутсрапа для своего проекта не обязательно устанавливать «Install Ruby, install Bundler with gem install bundler, and finally run bundle install. This will install all Ruby dependencies, such as Jekyll and plugins.» правильно я понял?
                                                                                                    1. Александр Мальцев
                                                                                                      18 ноября 2017, 15:57
                                                                                                      Да, вместо Bower для загрузки Bootstrap 4 можно использовать npm. Bower ушёл в прошлое, поэтому и возможность загрузки Bootstrap 4 с помощью него исчезла. Gulp конечно нет разницы, как вы будете загружать файлы.

                                                                                                      Да, такое количество пакетов нужно для сборки всего сайта.
                                                                                                      Если вам нужно только CSS, то необходимо установить только те, которые перечислены в таске css:build:
                                                                                                      // сбор стилей
                                                                                                      gulp.task('css:build', function () {
                                                                                                          gulp.src(path.src.style) // получим main.scss
                                                                                                              .pipe(sourcemaps.init()) // инициализируем sourcemap
                                                                                                              .pipe(sass()) // scss -> css
                                                                                                              .pipe(autoprefixer({ // добавим префиксы
                                                                                                                  browsers: autoprefixerList
                                                                                                              }))
                                                                                                              .pipe(cleanCSS()) // минимизируем CSS
                                                                                                              .pipe(sourcemaps.write('./')) // записываем sourcemap
                                                                                                              .pipe(gulp.dest(path.build.css)) // выгружаем в build
                                                                                                      });
                                                                                                      
                                                                                                      К gulp-sass и gulp-autoprefixer желательно добавить ещё gulp-clean-css (для минимизации CSS) и gulp-sourcemaps (для создания map файла CSS).

                                                                                                      Устанавливать Ruby и Bundler не нужно.
                                                                                                      1. Евгений
                                                                                                        18 ноября 2017, 22:26
                                                                                                        Спасибо вам большое за вашу статью и за ответ! Открыли новые горизонты для мамонта из каменных 2000-х когда странички верстали таблицами:)
                                                                                                    2. Иван
                                                                                                      10 ноября 2017, 14:20
                                                                                                      Добрый день
                                                                                                      Данную процедуру необходимо проводить перед каждым проектом или можно как то уже сделанный проект переносить в новую папку и делать другой сайт?
                                                                                                      1. Александр Мальцев
                                                                                                        11 ноября 2017, 16:41
                                                                                                        Добрый день!
                                                                                                        Как это выполнять каждый разработчик выбирает сам. Можете просто копировать.

                                                                                                        Ну, или делать так:
                                                                                                        1. Клонировать репозиторий в новый проект:
                                                                                                        git clone https://github.com/itchief/gulp-project-bootstrap-4.git
                                                                                                        2. Ввести 2 команды:
                                                                                                        npm install
                                                                                                        bower install
                                                                                                        
                                                                                                        После выполнения этих 2 действий gulp-проект будет настроен.
                                                                                                      2. ctac
                                                                                                        07 ноября 2017, 11:42
                                                                                                        Статья мега полезная. Пишите еще на такие темы. Еще лучше если бы задания были бы какие-то… А то прочитал, забыл и все…
                                                                                                        1. Александр Мальцев
                                                                                                          11 ноября 2017, 16:13
                                                                                                          Спасибо за отзыв.
                                                                                                        2. Константин
                                                                                                          27 октября 2017, 07:22
                                                                                                          Доброго времени суток, Александр!
                                                                                                          Использую в качестве локального сервера OpenServer.
                                                                                                          Возникла проблема при установке bower install:

                                                                                                          bower EMALFORMED Failed to read c:\openserver\userdata\temp\*******\bower\ca4c50b905dc21ea17a10549a6f5944f-9156-wPQQSX\bower.json

                                                                                                          Почему-то он ищет bower.json по этому пути c:\openserver\userdata\temp\*******\bower\ca4c50b905dc21ea17a10549a6f5944f-9156-wPQQSX, а не в папке проета? Там этого файла соответственно нет, хотя сам путь существует. Хотя команду запускаю через консоль из папки проекта.

                                                                                                          Сможете подсказать в «какую сторону копать», чтобы решить проблему?
                                                                                                          Спасибо.

                                                                                                          1. Teddy_GOD
                                                                                                            14 ноября 2017, 01:01
                                                                                                            Это значит что Вы создали файл bower.json до инициализации, удалите его и все заработает
                                                                                                            1. Александр Мальцев
                                                                                                              04 ноября 2017, 15:50
                                                                                                              Здравствуйте, Константин. Может вы находитесь в командной консоли в этой папке. Попробуйте перейти в корневую папку проекта и инициализировать bower в ней.
                                                                                                            2. anton
                                                                                                              26 октября 2017, 08:47
                                                                                                              Александр, а это дело без авто обновления, да?
                                                                                                              1. Александр Мальцев
                                                                                                                26 октября 2017, 11:39
                                                                                                                npm пакеты можно обновить так:
                                                                                                                npm i -g npm-check-updates
                                                                                                                npm-check-updates -u
                                                                                                                npm install
                                                                                                                Bower пакеты:
                                                                                                                bower update
                                                                                                              Войдите, пожалуйста, в аккаунт, чтобы оставить комментарий.