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

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

Основный список инструментов

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

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

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

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

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

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

Для этого в корне проекта создадим папку assets, файлы gulpfile.js (будет содержать задачи для сборщика проекта Gulp) и .bowerrc(конфигурационный файл для менеджера Bower с помощью которого будем загружать Bootstrap, jQuery и Popper). В папке assets создадим ещё 2 папки: src (для исходных кодов), build (для готовых файлов, их в эту папку будет помещать сборщик Gulp). В папке src создадим ещё 6 каталогов (bower_components, fonts, img, js, style и template) и 1 файл (index.html).

Директорию bower_components отведём под компоненты, которые будем загружать с помощью Bower.

Директорию fonts будем использовать под шрифты.

В директорию img будем помещать исходные файлы изображений.

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

Директорию style отведём под стили. В данной директории создадим 3 файла: 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 файлов (расположены в каталоге ./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).

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

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

Обратите внимание, что после копирования переменных Bootstrap 4 в свой файл CSS, у них необходимо убрать метку !default.

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

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

Кроме этого, к данному файлу можно также подключить файл с переопределёнными переменными Bootstrap, а также SCSS файл (например, my.scss), в котором вы будете описывать свои стили.

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

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

// Подключение нужных SCSS исходников Bootstrap 4
@import "../bower_components/bootstrap/scss/functions";
@import "../bower_components/bootstrap/scss/variables";
@import "../bower_components/bootstrap/scss/mixins";
@import "../bower_components/bootstrap/scss/reboot";
@import "../bower_components/bootstrap/scss/grid";
@import "../bower_components/bootstrap/scss/tables";
@import "../bower_components/bootstrap/scss/forms";
@import "../bower_components/bootstrap/scss/buttons";
@import "../bower_components/bootstrap/scss/transitions";
@import "../bower_components/bootstrap/scss/dropdown";
@import "../bower_components/bootstrap/scss/input-group";
@import "../bower_components/bootstrap/scss/nav";
@import "../bower_components/bootstrap/scss/navbar";
@import "../bower_components/bootstrap/scss/card";
@import "../bower_components/bootstrap/scss/pagination";
@import "../bower_components/bootstrap/scss/badge";
@import "../bower_components/bootstrap/scss/alert";
@import "../bower_components/bootstrap/scss/close";
@import "../bower_components/bootstrap/scss/utilities";

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

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

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

Список js файлов Bootstrap 4
Список js файлов Bootstrap 4

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

Импортирование нужных файлов в main.js будем осуществлять посредством Gulp плагина gulp-rigger (он будет установлен и подключен к проекту позже), используя следующую конструкцию:

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

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

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

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

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

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

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

Установка инструментов

Установим инструменты "Node.js", "Git", "Gulp" и "Bower". С помощью их будем создавать окружение для комфортной разработки фронтенд проекта.

Bootstrap 4 - Установка Node.js, Git, Gulp и Bower

Установка "Node.js". Скачиваем установщик Node.js для своей операционной системы, запускаем его и следуем инструкциям мастера.

Установка Git. Если у вас не установлен Git, то его необходимо установить в систему. Скачать дистрибутив можно со страницы Git – Downloading Package.

Установка Gulp. Для установки Gulp необходимо открыть командную консоль и выполнить в ней команду:

npm install -g gulp
Установка Gulp
Установка Gulp

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

Установка Bower. Установка Bower выполняется также как и Gulp.

npm install -g bower

Инициализация проекта и установка зависимостей

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

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

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

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

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

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

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

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

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

npm install название_пакета --save-dev  

Ключ --save-dev необходим, чтобы при установке пакета, информация о нём, автоматически прописывалась в секцию devDependencies файла package.json.

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

npm install gulp --save-dev // установка gulp
npm install browser-sync --save-dev // установка browser-sync (плагина для gulp)
npm install del --save-dev // установка del (плагина для gulp)
npm install gulp-autoprefixer --save-dev // установка gulp-autoprefixer (плагина для gulp)
npm install gulp-cache --save-dev // установка gulp-cache
npm install gulp-clean-css --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

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

{
  "name": "bootstrap-4",
  "version": "1.0.0",
  "description": "Start project on Bootstrap 4 - itchief.ru",
  "author": "itchief.ru",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.18.13",
    "del": "^3.0.0",
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^4.0.0",
    "gulp-cache": "^0.4.6",
    "gulp-clean-css": "^3.9.0",
    "gulp-imagemin": "^3.3.0",
    "gulp-plumber": "^1.1.0",
    "gulp-rigger": "^0.5.8",
    "gulp-sass": "^3.1.0",
    "gulp-sourcemaps": "^2.6.1",
    "gulp-uglify": "^3.0.0",
    "imagemin-jpeg-recompress": "^5.1.0",
    "imagemin-pngquant": "^5.0.1"
  }
}

Если вы не хотите выполнять все перечисленные действия, то достаточно создать в корневой папке файл package.json с вышепредставленным содержимым и ввести команду:

npm install

После этого все зависимости проекта будут установлены автоматически.

Инициализация 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

Создание сборщика проекта (gulpfile.js)

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

Файл gulpfile.js представляет собой список задач, которые будут выполнять следующие действия:

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

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

Откроем файл 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
    del = require('del'); // плагин для удаления файлов и каталогов

/* задачи */

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

// сбор html
gulp.task('html:build', function () {
    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 () {
    gulp.src(path.src.style) // получим main.scss
        .pipe(plumber()) // для отслеживания ошибок
        .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
        .pipe(webserver.reload({stream: true})); // перезагрузим сервер
});

// сбор js
gulp.task('js:build', function () {
    gulp.src(path.src.js) // получим файл main.js
        .pipe(plumber()) // для отслеживания ошибок
        .pipe(rigger()) // импортируем все указанные файлы в main.js
        .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() {
    gulp.src(path.src.fonts)
        .pipe(gulp.dest(path.build.fonts));
});

// обработка картинок
gulp.task('image:build', function () {
    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 () {
    del.sync(path.clean);
});

// очистка кэша
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', [
    'clean:build',
    'build',
    'webserver',
    'watch'
]);

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

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

Функционал же задачи в большинстве случаев состоит из следующих действий:

  • выборки исходных файлов;
  • вызова различных плагинов, которые делают что-то с этими файлами;
  • выгрузки полученных файлов в папку назначения.

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

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

gulp

После ввода этой команды запустится задача по умолчанию (default). Эта задача запустит задачи build, webserver и watch. Задача build осуществит сборку проекта для продакшена. Все полученные файлы она поместит в папку build. Задача webserver запустит локальный веб-сервер с «живой перезагрузкой» страниц. Задача watch будет отслеживать изменения исходных файлов в папке src и автоматически запускать необходимые задачи. В результате содержимое папки build всегда будет находиться в актуальном состоянии.

Запуск gulp
Запуск gulp

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