Настройка gulpfile.js

Создадим папку gulp-skeleton. В этой папке создадим файл package.json со следующим содержимым:

{
	"name": "Gulp_Skeleton",
	"version": "1.0.0",
	"description": "Gulp 4 skeleton",
	"author": "Orkhan Alyshov"
}

Переходим в папку проекта

cd gulp-skeleton

и выполняем команду:

npm install --save-dev gulp

После выполнения этой команды, в папке нашего проекта появится папка node_modules и файл package-lock.json.

Таким образом мы установили gulp. Теперь содержимое package.json выглядит так:

{
	"name": "Gulp_Skeleton",
	"version": "1.0.0",
	"description": "Gulp 4 skeleton",
	"author": "Orkhan Alyshov",
	"devDependencies": {
		"gulp": "^4.0.2"
	}
}

Создадим новый файл в корне проекта gulpfile.js со следующим содержимым:

"use strict";

const {src, dest} = require("gulp");
const gulp = require("gulp");

Установка необходимых плагинов

- gulp-autoprefixer

npm install --save-dev gulp-autoprefixer

- gulp-cssbeautify

npm install --save-dev gulp-cssbeautify

- gulp-strip-css-comments

npm install --save-dev gulp-strip-css-comments

- gulp-html-beautify

npm install --save-dev gulp-html-beautify

- gulp-remove-html-comments

npm install --save-dev gulp-remove-html-comments

- gulp-rename

npm install --save-dev gulp-rename

- gulp-sass

npm install --save-dev gulp-sass

- gulp-cssnano

npm install --save-dev gulp-cssnano

- gulp-rigger

npm install --save-dev gulp-rigger

- gulp-uglify

npm install --save-dev gulp-uglify

- gulp-plumber

npm install --save-dev gulp-plumber

- gulp-imagemin

npm install --save-dev gulp-imagemin

- del

npm install --save-dev del

- panini

npm install --save-dev panini

- browser-sync

npm install --save-dev browser-sync

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

{
    "name": "Gulp_Skeleton",
    "version": "1.0.0",
    "description": "Gulp 4 skeleton",
    "author": "Orkhan Alyshov",
    "devDependencies": {
        "browser-sync": "^2.26.7",
        "del": "^5.1.0",
        "gulp": "^4.0.2",
        "gulp-autoprefixer": "^7.0.1",
        "gulp-cssbeautify": "^2.0.0",
        "gulp-cssnano": "^2.1.3",
        "gulp-html-beautify": "^1.0.1",
        "gulp-imagemin": "^6.1.1",
        "gulp-plumber": "^1.2.1",
        "gulp-remove-html-comments": "^1.0.1",
        "gulp-rename": "^1.4.0",
        "gulp-rigger": "^0.5.8",
        "gulp-sass": "^4.0.2",
        "gulp-strip-css-comments": "^2.0.0",
        "gulp-uglify": "^3.0.2",
        "panini": "^1.6.3"
    }
}

Теперь нужно подключить установленные плагины в файле gulpfile.js:

"use strict";

const {src, dest} = require("gulp");
const gulp = require("gulp");
const autoprefixer = require("gulp-autoprefixer");
const cssbeautify = require("gulp-cssbeautify");
const removeCommentsCSS = require("gulp-strip-css-comments");
const htmlbeautify = require("gulp-html-beautify");
const removeCommentsHTML = require("gulp-remove-html-comments");
const rename = require("gulp-rename");
const sass = require("gulp-sass");
const cssnano = require("gulp-cssnano");
const rigger = require("gulp-rigger");
const uglify = require("gulp-uglify");
const plumber = require("gulp-plumber");
const imagemin = require("gulp-imagemin");
const del = require("del");
const panini = require("panini");
const browsersync = require("browser-sync").create();

Структура проекта

В корне нашего проекта gulp-skeleton создадим папку src. В этой папке будут храниться все исходники нашего проекта. В папке src создадим папку assets. В папке assets создадим папки js, sass, img. В корне папки src будут .html файлы.


Gulp таски

Напишем Gulp таски. Вот конечный вид файла gulpfile.js:

"use strict";

const {src, dest} = require("gulp");
const gulp = require("gulp");
const autoprefixer = require("gulp-autoprefixer");
const cssbeautify = require("gulp-cssbeautify");
const removeCommentsCSS = require("gulp-strip-css-comments");
const htmlbeautify = require("gulp-html-beautify");
const removeCommentsHTML = require("gulp-remove-html-comments");
const rename = require("gulp-rename");
const sass = require("gulp-sass");
const cssnano = require("gulp-cssnano");
const rigger = require("gulp-rigger");
const uglify = require("gulp-uglify");
const plumber = require("gulp-plumber");
const imagemin = require("gulp-imagemin");
const del = require("del");
const panini = require("panini");
const browsersync = require("browser-sync").create();

let path = {
    build: {
        html: "dist/",
        js: "dist/assets/js",
        css: "dist/assets/css",
        images: "dist/assets/img"
    },
    src: {
        html: "src/*.html",
        js: "src/assets/js/*.js",
        css: "src/assets/sass/style.scss",
        images: "src/assets/img/**/*.{jpg,png,svg,gif,ico,webmanifest,xml}"
    },
    watch: {
        html: "src/**/*.html",
        js: "src/assets/js/**/*.js",
        css: "src/assets/sass/**/*.scss",
        images: "src/assets/img/**/*.{jpg,png,svg,gif,ico,webmanifest,xml}"
    },
    clean: "./dist"
};

/* Tasks */
function browserSync(done) {
    browsersync.init({
        server: {
            baseDir: "./dist/",
        },
        port: 3000
    });
}

function browserSyncReload(done) {
    browsersync.reload();
}

function html() {
    panini.refresh();

    return src(path.src.html, { base: "src/" })
        .pipe(plumber())
        .pipe(panini({
            root: "src/",
            layouts: "src/tpl/layouts/",
            partials: "src/tpl/partials/",
            data: "src/tpl/data/",
        }))
        .pipe(htmlbeautify({
            indentSize: 4,
        }))
        .pipe(removeCommentsHTML())
        .pipe(dest(path.build.html))
        .pipe(browsersync.stream());
}

function css() {
    return src(path.src.css, { base: "src/assets/sass/" })
        .pipe(plumber())
        .pipe(sass())
        .pipe(autoprefixer({
            overrideBrowserslist: ['last 10 versions'],
            cascade: true
        }))
        .pipe(cssbeautify())
        .pipe(removeCommentsCSS())
        .pipe(dest(path.build.css))
        .pipe(cssnano({
            zindex: false,
            discardComments: {
                removeAll: true
            }
        }))
        .pipe(rename({
            suffix: ".min",
            extname: ".css"
        }))
        .pipe(dest(path.build.css))
        .pipe(browsersync.stream());
}

function js() {
    return src(path.src.js, { base: "./src/assets/js/" })
        .pipe(plumber())
        .pipe(rigger())
        .pipe(gulp.dest(path.build.js))
        .pipe(uglify())
        .pipe(rename({
            suffix: ".min",
            extname: ".js"
        }))
        .pipe(dest(path.build.js))
        .pipe(browsersync.stream());
}

function images() {
    return src(path.src.images)
        .pipe(imagemin())
        .pipe(dest(path.build.images));
}

function clean() {
    return del(path.clean);
}

function watchFiles() {
    gulp.watch([path.watch.html], html);
    gulp.watch([path.watch.css], css);
    gulp.watch([path.watch.js], js);
    gulp.watch([path.watch.images], images);
}

const build = gulp.series(clean, gulp.parallel(html, css, js, images));
const watch = gulp.parallel(build, watchFiles, browserSync);

/* Export tasks */
exports.html = html;
exports.css = css;
exports.js = js;
exports.images = images;
exports.clean = clean;
exports.build = build;
exports.watch = watch;
exports.default = watch;

Работа с библиотеками

Рассмотрим как подключаются сторонние библиотеки при помощи npm. Разберем на примере slick-carousel.

Выполняем следующую команду:

npm install slick-carousel --save

Библиотеку мы устанавливаем с флагом --save, а не --save-dev. Потому что эта библиотека нужна для работы сайта, она не зависимость gulp плагина, которая нужна для разработки.

Наш файл package.json изменился:

{
    "name": "Gulp_Skeleton",
    "version": "1.0.0",
    "description": "Gulp 4 skeleton",
    "author": "Orkhan Alyshov",
    "devDependencies": {
        "browser-sync": "^2.26.7",
        "del": "^5.1.0",
        "gulp": "^4.0.2",
        "gulp-autoprefixer": "^7.0.1",
        "gulp-cssbeautify": "^2.0.0",
        "gulp-cssnano": "^2.1.3",
        "gulp-html-beautify": "^1.0.1",
        "gulp-imagemin": "^6.1.1",
        "gulp-plumber": "^1.2.1",
        "gulp-remove-html-comments": "^1.0.1",
        "gulp-rename": "^1.4.0",
        "gulp-rigger": "^0.5.8",
        "gulp-sass": "^4.0.2",
        "gulp-strip-css-comments": "^2.0.0",
        "gulp-uglify": "^3.0.2",
        "panini": "^1.6.3"
    },
    "dependencies": {
        "slick-carousel": "^1.8.1"
    }
}

В папке src/assets/js/components создадим файл slick.js и подключим установленную библиотеку:

//= ../../../../node_modules/slick-carousel/slick/slick.js

$(".slider").slick({
    // options
})

Мы ничего не должны менять в папке node_modules!

Для стилизации можем скопировать файл node_modules/slick-carousel/slick/slick.scss в папку src/assets/sass/vendor/slick.scss.

После этого, мы можем в файле src/assets/js/app.js подключить js файл:

//= components/slick.js

а в файле src/assets/sass/style.scss подключить sass файл:

@import "vendor/slick";

Модульная работа с Bootstrap 4

Установим BS4 через npm:

npm install bootstrap --save

Вот наш файл package.json:

{
    "name": "Gulp_Skeleton",
    "version": "1.0.0",
    "description": "Gulp 4 skeleton",
    "author": "Orkhan Alyshov",
    "devDependencies": {
        "browser-sync": "^2.26.7",
        "del": "^5.1.0",
        "gulp": "^4.0.2",
        "gulp-autoprefixer": "^7.0.1",
        "gulp-cssbeautify": "^2.0.0",
        "gulp-cssnano": "^2.1.3",
        "gulp-html-beautify": "^1.0.1",
        "gulp-imagemin": "^6.1.1",
        "gulp-plumber": "^1.2.1",
        "gulp-remove-html-comments": "^1.0.1",
        "gulp-rename": "^1.4.0",
        "gulp-rigger": "^0.5.8",
        "gulp-sass": "^4.0.2",
        "gulp-strip-css-comments": "^2.0.0",
        "gulp-uglify": "^3.0.2",
        "panini": "^1.6.3"
    },
    "dependencies": {
        "bootstrap": "^4.3.1",
        "slick-carousel": "^1.8.1"
    }
}

В папке node_modules/bootstrap/scss находятся все исходные файлы для модульной разработки. Мы можем подключать отдельные компоненты. Если нужна только сетка bootstrap - подключаем компонент сетки, если нужны только кнопки - подключаем компонент для кнопок и т.д. Мы можем подключать необходимые компоненты в файле src/assets/sass/style.scss.

Для корректной работы необходимо подключить functions.scss, variables.scss, mixins.scss. Сначала подключаем их в файле src/assets/sass/style.scss:

@import "../../../node_modules/bootstrap/scss/functions";
@import "../../../node_modules/bootstrap/scss/variables";
@import "../../../node_modules/bootstrap/scss/mixins";

Например, нам необходимо подключить компонет сетки:

@import "../../../node_modules/bootstrap/scss/functions";
@import "../../../node_modules/bootstrap/scss/variables";
@import "../../../node_modules/bootstrap/scss/mixins";
@import "../../../node_modules/bootstrap/scss/grid";

Теперь подключим js компоненты BS4. Например, модальные окна. Файл src/assets/js/app.js:

//= ../../../node_modules/bootstrap/js/dist/util.js
//= ../../../node_modules/bootstrap/js/dist/modal.js