Gulp 4 - установка і настройка. Створення Gulp збірки для верстки сайту
RU
UK

Gulp

27 Серпня 2021 р.
Зміст

Що таке gulp і навіщо він потрібен

Gulp – це інструмент, який допомагає розробникам автоматизувати рутинні завдання. Найчастіше gulp використовується в frontend розробці для таких завдань:

  • Автоматична перезавантаження браузера при збереженні файлу
  • Використання препроцесорів
  • Оптимізація ресурсів таких як javascript, css, зображення
  • Використання автопрефіксера
  • Створення карт проекту
  • Об’єднання декількох файлів в один

Якщо ви упровадите в свою практику цю систему, ви значно збільшите швидкість вашої роботи. Так само gulp відкриє вам шлях до нових можливостей, який значно підвищить ваш рівень знань в веб-розробки.

Установка Gulp

Установка Gulp 4 досить проста. Так як Gulp написаний на мові javascript, спочатку необхідно встановити Node.js на вашу систему. Просто заходите на сайт https://nodejs.org, завантажуєте інсталятор останній версії і встановлюєте.

Далі створюємо папку для проекту в будь-якому зручному місці комп’ютера і викликаємо вікно терміналу в цьому каталозі. У командному рядку запускаємо ініціалізацію проекту:

npm init

Відповідаємо на питання на кожному кроці. Після кожного введення натискаємо Enter та переходимо до наступного кроку. В результаті отримаємо файл package.json, який містить інформацію про проект та встановлених плагинах. Далі встановимо gulp в наш проект:

npm i gulp --save-dev

Після установки Gulp 4 назва пакета та його версія збережуться в файлі package.json. Мітка –save-dev використовується для збереження пакета в package.json в розділ devDependencies, тобто з метою розробки. Якщо встановити пакет з міткою –save, то пакет потрапляє в розділ dependencies (для запуску програми).

Такий підхід дає можливість зберігати всі пакети в файлі package.json з усіма залежностями, а при розгортанні нового проекту досить скопіювати файл package.json і запустити команду:

npm install

Таким чином всі пакети та залежності встановляться автоматично. Після установки gulp в каталозі проекту створилася папка node_modules. Всі нові встановлені пакети та залежності зберігаються до папки. Тому змінювати вміст цього каталогу не можна.

Далі в каталозі проекту створюємо файл gulpfile.js. Це найголовніший файл, без якого Gulp працювати не може. По суті в нього можна писати будь який javascript код, але gulp — це менеджер управління завданнями, і ці завдання описуються в цьому файлі у вигляді звичайних функцій. Що б запускати ці завдання, функцію потрібно експортувати через оператор exports. Приклад:

function testTask(done){
    console.log('test');
    done();
}

exports.test = testTask;

На прикладі вище ми створили завдання під назвою testTask, в якій виводимо стрічку test. Після цього ми експортуємо цю задачу. Що б Gulp знав, що завдання виконане, ми викликаємо функцію зворотного виклику done.

Що б запустити Gulp, можна встановити окрему утиліту глобально на вашу систему:

npm install --global gulp-cli

Після цього в консолі вводимо команду gulp і через пробіл назва завдання:

gulp test

Але є й альтернативний варіант. Можна передати додаткові параметри командам запуску в файлі package.json для розділу scripts:

...

"scripts": {
    "gulp": "gulp"
},

...

В цьому випадку запускається задача так:

npm run gulp test

gulp – це значення з розділу scripts файлу package.json, а test – назва завдання. У підсумку в консолі виведеться слово test:Демонстрація тестового таска

Завдання за замовчуванням (gulp default task)

Створимо в файлі gulpfile.js завдання за замовчуванням. Цей такс найкраще представити, як точку входу в наш проект. Мета цього завдання — зібрати і запустити таски в певній послідовності, які gulp повинен виконати за замовчуванням. У нашому випадку ми замінимо таск test на default в функції експорту:

exports.default = testTask;

Тепер для запуску проекту нам необхідно ввести:

npm run gulp

Таким чином ми отримаємо такий же результат, як і раніше, але при цьому ми не вказуємо конкретний таск, а запускаємо завдання за замовчуванням.

Gulp parallel, gulp series

У Gulp існують методи parallel і series для об’єднання завдань в ланцюжки. Метод parallel запускає завдання одночасно в будь-якій послідовності. Метод series — виконує завдання одна за однією в зазначеному порядку:

exports.default = gulp.series( gulp.parallel(a, b), gulp.parallel(c, d) )

На прикладі вище, завдання a і b запускаються паралельно. Тільки після завершення цих завдань, запускаються таски c і d в паралельному режимі.

Gulp src, gulp dist, gulp pipe

Перш ніж приступати до практики, визначимося ще з деякими базовими поняттями. Раніше ми створили тестовий таск, який просто виводить значення в консоль. Але сенс gulp в тому, щоб виконувати рутинні завдання в процесі розробки. Іншими словами — взяти якийсь файл нашого проекту, виконати певні маніпуляції з ним, і на виході отримати оновлений файл. Для того, щоб вказати вхідний файл, використовується вираз gulp.src( ‘source-file’), а вихідний — gulp.dest ( ‘dest-folder’). Давайте розглянемо на прикладі:

const gulp = require('gulp');
function testTask(){
    return gulp.src('./test.js')
        .pipe(gulp.dest('./output'));
}
exports.default = testTask;

Першим рядком підключаємо сам gulp в наш проект. Далі створюємо таск, як ми робили це раніше. Вказуємо gulp що ми працюємо з файлом test.js. Після цього через метод pipe говоримо gulp, що вихідна папка називається output. Таким чином ми просто скопіювали файл test.js в папку output.

Метод pipe — це основне API для gulp. Цей метод як би об’єднує всі операції всередині таска. Через pipe можна вибудувати необмежену ланцюжок з операцій для створення певних сценаріїв.

Шаблони шляхів до файлів

Дуже часто необхідно на вхід gulp передати не конкретний файл, а групу файлів. Для цього використовують так звані шаблони. Розглянемо на прикладі які вони бувають:

./input/*.js— вибере всі файли з розширенням js в корені папки input

./input/**/*.js— вибере всі файли з розширенням js в корені папки input і дочірніх каталогах

!./input/test.js— виключає файл test.js з вибірки

./input/*.+(js, css)— вибере файли js і css

Так само, як вхідні дані в gulp можна передавати масив з декількома файлами або шаблонами:

gulp.src(["./input/**/*.css", "!./input/test.css"])

На прикладі ми вибираємо всі файли з розширенням css, але виключаємо файл test.css.

Gulp плагіни

Стандартний функціонал gulp досить примітивний. Для того, щоб реалізувати більш складні операції, необхідно використовувати так звані плагіни. Іншими словами, це розширення, яке ми підключаємо до себе в проект для вирішення того чи іншого завдання. Існує величезна кількість плагінів для gulp. Знайти і подивитися їх опис можна на офіційному сайті.

Раніше ми написали скрипт, який просто копіює файл в іншу папку. Давайте ускладнити завдання: при копіюванні ім’я файлу повинна перейменовується. Для цього якраз і скористаємося плагіном, який називається gulp-rename. Для початку, встановимо цей плагін:

npm i gulp-rename --save-dev

Будь-плагін, як і npm модуль, встановлюється в папку node_modules, і потрапляє в файл package.json. Далі його потрібно підключити в gulpfile.js, і через метод pipe викликати необхідну операцію:

const gulp = require('gulp');
const rename = require("gulp-rename");

function testTask(){
    return gulp.src('./test.js')
        .pipe(rename('testNew.js'))
        .pipe(gulp.dest('./output'));
}
exports.default = testTask

Таким чином, ми беремо файл test.js, перейменовуємо його в testNew.js, і копіюємо в папку output.

Gulp збірка для верстки сайту

І так, ми встановили Gulp, налаштували оточення і можемо переходити до створення своєї збірки для верстки сайту.

Для початку поставимо собі завдання: ми хочемо створити гнучку заготовку для початку роботи з будь-яким проектом. Збірка буде виконувати ряд завдань: робота з препроцесора, мініфікація коду, стиснення і перетворення зображень, конвертація шрифтів, збірка спрайтів, підключення окремий частин html в єдиний шаблон і багато іншого.

Режими роботи

Gulp збірка повинна запускатися в двох режимах: збірка проекту для розробки і складання для продакшн. У режимі розробки важлива швидкість роботи, тому ми не будемо мініфіціровать код, стискати зображення і виконувати інші трудомісткі операції. У режимі продакшн ми готуємо наш проект до подальшого використання або вивантаженні на хостинг, очищаємо від всього зайвого, стискаємо код і виконуємо інші дії. Давайте це реалізуємо.

У файлі package.json в розділ scripts вносимо деякі зміни:

...

"scripts": {
    "dev": "gulp",
    "prod": "gulp --prod"
},

...

Для запуску збірки в режимі розробки необхідно ввести команду:

npm run dev

Для запуску в режимі продакшн:

npm run prod

Як бачимо вище, в режимі прод ми додаємо змінну оточення prod. Далі, щоб визначити в якому режимі ми працюємо, необхідно встановити плагін yargs:

npm i yargs --save-dev

Підключаємо цей плагін в gulpfile.js:

const argv = require('yargs').argv;

Якщо запустити збірку в режимі дів, то значення змінної argv.prod дорівнюватиме undefined, а якщо в прод режимі, то true. Таким чином, якщо змінна argv.prod дорівнює true, то ми працюємо в прод режимі. Якщо не true, то дев режим.

Для зручності, створимо дві функції, які перевіряють режим роботи:

/**
 * Dev check
 */
const isDev = function(){
    return !argv.prod;
}

/**
 * Prod check
 */
const isProd = function(){
    return !!argv.prod;
}

Файлова структура gulp збірки

Створимо базову структуру файлів і папок. Це стандартна структура будь-якого web проекту, яку можна поміняти під свій смак і потреби.gulpProject: . | gulpfile.js | package-lock.json | package.json +—dist +—src | index.html +—assets | +—css | +—fonts | +—img | +—js +—_components

Розглянемо призначення кожної папки і файлу:

  • gulpfile.js— головний файл для настройки Gulp4
  • package-lock.json— файл створюється автоматично при зміні в node_modules
  • package.json— файлу-маніфесту для проекту
  • dist— в цю папку автоматично зберігаються всі готові файли. Іншими словами в цій папці міститься готовий проект
  • src— в цьому каталозі зберігаються вихідні проекту
  • index.html— шаблон головної сторінки
  • assets— папка для активів, таких, як стилі, скрипти, шрифти та ін
  • css— файли для препроцесора CSS
  • fonts— каталог для шрифтів
  • img— папка для вихідних зображень
  • js— каталог для вихідних скриптів

Це основна файлова структура збірки, але вона буде змінюватися в ході роботи.

Давайте відразу додамо файл .gitignore в корінь проекту з наступним змістом:

/node_modules/*
/dist/*

Тут ми приховуємо каталоги dist та node_modules від систем контроль версій, так як вони створюються автоматично.

Налаштування шляхів

Створимо в корені проекту файл projectConfig.json. Це простий json файл, в нього ми будемо записувати різні настройки для нашої збірки. Для початку визначимо змінні для шляхів:

{
    "path": {
        "src": {
            "srcPath": "./src",
        },
        "dist": {
            "distPath": "./dist"
        }
    }
}

Ми визначили змінну path, яка в свою чергу містить два значення: настройки шляхів для початкових кодів проекту і для готового результату. В кінцевому підсумку ми можемо змінювати ці значення, що дає гнучкість нашої gulp збірки. У процесі роботи ми будемо додавати необхідні нам налаштування.

Далі в gulpfile.js підключимо файл з настройками:

const projectConfig = require('./projectСonfig.json');
const path = projectConfig.path;

Тепер можна звернеться до змінної path і отримати необхідні значення.

Browser sync gulp. Автоматичне оновлення сторінки в браузері

Browser sync — це дуже корисний плагін. Він дозволяє відкрити сторінки сайту, використовуючи локальний сервер, і налаштувати автоматичну перезавантаження сайту. Встановимо плагін browsersync в наш проект:

npm install browser-sync gulp --save-dev

У файлі gulpfile.js додамо опис таска для плагіна browsersync. На даному етапі файл gulpfile.js виглядає так:


const gulp = require('gulp');
const argv = require('yargs').argv;
const browserSync = require('browser-sync').create();

const projectConfig = require('./projectСonfig.json');

const path = projectConfig.path;

const isDev = function(){
    return !argv.prod;
}

const isProd = function(){
    return !!argv.prod;
}

function browsersync() {
    browserSync.init({
            open: true,
            server: path.dist.distPath
    });
}
exports.default = browsersync;

Все як завжди: підключаємо browserSync через require, описуємо завдання для нього, і запускаємо таск за замовчуванням. Тепер при запуску gulp автоматично відкриється браузер. На даному етапі нам цього буде достатньо.

Gulp html

Для роботи з html, будемо використовувати шаблонизатор nunjucks (докладніше почитати можна тут ). Для початку визначимо структуру каталогу і файлів для штмл файлів:src: . | index.html +— _html +— _base +— _includes | _header.html | _footer.html +— _layouts | _default.html

Розглянемо докладніше файлову структуру:

  • index.html— головна сторінка сайту
  • _ includes— каталог з підключаються файлами
  • _ header.html— верхня частина сайту
  • _ footer.html— нижня частина сайту
  • _ layouts— папка з шаблонами
  • _ default.html— основний шаблон

Нижній прочерк в назві файлів і папок говорить про те, що вони підключаються до основного файл.

Далі задамо налаштування шляхів для html в файлі projectСonfig.json. В розділ src додамо масив із значенням папки, де знаходяться штмл файли, щодо каталогу з кодами проекту. Аналогічно додамо значення для вихідного файлу в розділ dist.

{
    "path": {
        "src": {
            "srcPath": "./src",
            "components": "/_components",
            "html": [
                "/**/*.html"
            ]
        },
        "dist": {
            "distPath": "./dist",
            "html": "/"
        }
    }
}

У gulpfile.js створимо масив шляхів для вхідних файлів:

path.src.html[0] =  path.src.srcPath + path.src.html[0];
path.src.html[1] =  "!" + path.src.html[0].slice(0, -6) + "_*.html";
path.src.html[2] =  "!" + path.src.srcPath + "/assets";
path.src.html[3] =  "!" + path.src.srcPath + "/_html";

У першому рядку формуємо шлях до html файлів, які потрібно скомпілювати. У другій забороняємо компілювати файли, які починаються з нижнього прочерку. У третьої та четвертої забороняємо компіляцію з папки assets і _html. В результаті отримаємо такий масив:

html: [
  './src/**/*.html',
  '!./src/**/_*.html',
  '!./src/assets',
  '!./src/_html'
]

Так само формуємо змінну для папки з готовими html файлами:

path.dist.html = path.dist.distPath + path.dist.html;

В результаті отримаємо таке значення:

html: './dist/'

І так, шляхи ми сформували, тепер описуємо завдання для html файлів:

function njk() {
    return gulp.src(path.src.html)
        .pipe(nunjucks.compile())
        .pipe(gulp.dest(path.dist.html))
        .on('end', browserSync.reload);
}
exports.njk = njk;

Як бачимо, це звичайне завдання для gulp. В кінці цього таска ми автоматично перезавантажуємо браузер.

Створимо загальний каркас для всіх сторінок сайту в файлі _default.html:

<!DOCTYPE html>
<html lang="en">
<head>    
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{ title }}</title>
    <meta name="description" content="{{ meta_description }}">
</head>
<body {% if bodyClass %}class="{{ bodyClass }}"{% endif %}>
    <div class="page-wrapper" id="pageWrapper">
        {% include "_html/_base/_includes/_header.html" %}

        {% block content %}{% endblock %}

        {% include "_html/_base/_includes/_footer.html" %}
    </div>    
</body>
</html>

У файлах _header.html і _footer.html виведемо верхню і нижню частини сайту, які ми підключаємо до основного шаблоном. _header.html:

<header>Header</header>

_footer.html:

<footer>Footer</footer>

У файлі index.html знаходиться основна частина головної сторінки сайту:

{% set title = "Home" %}
{% set bodyClass = "is-home" %}

{% extends "_html/_base/_layouts/_default.html" %}

{% block content %}
    <h1>Content</h1>
{% endblock %}

На прикладі вище ми визначили змінні title сторінки і класу тега body. В процесі роботи можна додавати інші змінні і передавати їх в основний шаблон. Далі ми вказуємо, що успадковуємо основний шаблон і в блоці content описуємо контентную частина сторінки.

Таким чином ми можемо створювати спільні html файли для нашого проекту, підключати їх в шаблон і міняти вміст в одному місці.

Тепер запустимо на виконання таск:

Як бачимо, все вихідні скомпілювати в один файл index.html. Тепер можна створювати скільки завгодно html файлів і всі вони будуть збиратися в папці dist.

Gulp watch. Відстежуємо зміни в файлах

У Gulp передбачений метод watch, за допомогою якого можна відстежувати зміни в тому чи іншому файлі. Якщо ми, наприклад, модифікували наш файл index.html, то за допомогою методу watch можна автоматично запустити той чи інший таск. Реалізуємо це в нашій збірці.

Для початку в змінної path визначимо властивість watch як порожній об’єкт:

path.watch = {};

У ній вкажемо файли, які потрібно відстежувати для збірки html:

path.watch.html = [];
path.watch.html[0] = path.src.html[0];

Тобто, ми відстежуємо всі файли в папці src. Створимо gulp tack для відстеження змін в файлах:

function watch(){
    gulp.watch(path.watch.html, njk);
}

На прикладі вище ми створили звичайний таск, в ньому викликаємо метод watch, в який передаємо два параметри: які фали відстежуємо, і який таск запускаємо при модифікації в цих файлах.

Після цього змінимо дефолтний таск:

exports.default = gulp.series(
    gulp.parallel(njk),
    gulp.parallel(browsersync, watch)
);

Тут спочатку запускається таск njk, після цього в паралельному режимі запускаємо локальний сервер і відстеження в файлах.

Тепер при запуску дефолтного таска відкриється головна сторінка на локальному сервері. При зміні в штмл файлах сайт оновлюється автоматично вже з зміненими даними.

Gulp scss. Робота зі стилями

Як препроцесора для стилів будемо використовувати SASS в синтаксисі SCSS. В папці src / assets / css створимо файл app.scss. Це буде основний файл стилів.

У projectСonfig.json задаємо настройки шляхів до файлів стилів. У розділі src додаємо:

"style": [
    "/assets/css/app.scss"
]

В розділ dist:

"style": "/assets/css/"

У gulpfile.js задаємо масив шляхів для файлів стилів:

path.src.style[0] = path.src.srcPath + path.src.style[0];

path.dist.style = path.dist.distPath + path.dist.style;

path.watch.style = [];
path.watch.style[0]  = path.src.style[0].replace( path.src.style[0].split('/').pop(), '**/*.scss' );

В результаті отримаємо:

  • Вхідний файл:./src/assets/css/app.scss
  • Вихідна директорія:./dist/assets/css/
  • Файли для відстеження:./src/assets/css/**/*.scss

Відразу відкриємо наш основний шаблон _default.html і в розділ head додамо файл стилів, який буде називається app.min.css:

<link rel="stylesheet" type="text/css" href="assets/css/app.min.css">

Далее добавляем нужные плагины для работы со стилями:

npm i sass gulp-sass gulp-sourcemaps gulp-autoprefixer gulp-csso gulp-rename gulp-group-css-media-queries gulp-if  --save-dave
  • sass — скрипт компіляції sass файлів
  • gulp-sass — gulp плагін для sass
  • gulp-sourcemaps — плагін для source maps, який дозволяє в DevTools відстежувати стилі в початкових файлах
  • gulp-autoprefixer — плагін для розстановки префіксів
  • gulp-csso — плагін для мініфікаціі css
  • gulp-rename — плагін для перейменування файлів
  • gulp-group-css-media-queries — плагін для угруповання медіа запитів в стилях
  • gulp-if — плагін для створення умов в gulp файлі

Підключаємо всі ці плагіни:

const sass = require('gulp-sass')(require('sass')); 
const sourcemaps = require('gulp-sourcemaps');
const gulpif = require('gulp-if');
const autoprefixer = require('gulp-autoprefixer');
const csso = require('gulp-csso');
const rename = require("gulp-rename");
const gcmq = require('gulp-group-css-media-queries');

Далі створюємо gulp таск для CSS стилів:

function scss(){
    return gulp.src(path.src.style)
        .pipe(gulpif(isDev(), sourcemaps.init()))
        .pipe(sass())
        .pipe(gulpif(isProd(), autoprefixer({
            grid: true
        })))
        .pipe(gulpif(isProd(), gcmq()))
        .pipe(gulpif(isDev(), sourcemaps.write()))
        .pipe(gulpif(isProd(), gulp.dest(path.dist.style)))
        .pipe(gulpif(isProd(), csso()))
        .pipe(rename({ suffix: '.min' }))
        .pipe(gulp.dest(path.dist.style))
        .pipe(browserSync.reload({stream: true}))
}

Розглянемо детально код вище. За допомогою плагіна gulpif ми перевіряємо в якому режимі ми працюємо. Якщо в дев режимі, то ми инициализируем sourcemaps, виконуємо компіляцію sass, зберігаємо sourcemaps в кінець файлу, додаємо суфікс min до назви файлу, зберігаємо готовий файл і перезавантажуємо браузер. Таким образів, в папці dist/css створиться файл app.min.css. Незважаючи на те, що ми додали суфікс min, стилі в ньому не стиснуті і додані sourcemaps для зручності розробки.

В прод режимі нам потрібно оптимізувати стилі і підготувати для бойових умов. Після компіляції SASS додаються префікси, групуються медіа запити (gulp group css media queries). Далі ми зберігаємо нестислий файл стилів в папку dist/css. Цей файл називається app.css і він не буде підключений до сайту. Зроблено це для зручності, що б поруч зі стисненим файлом був оригінальний файл стилів. Далі ми мініфіціруем стилі, додаємо суфікс min, зберігаємо і перенавантажуємо браузер. В результаті отримаємо файл app.min.css, який оптимізований і підключений до проекту.

Тепер потрібно трохи налаштувати автопрефіксер, вказати які браузери потрібно підтримувати. Це можна зробити, додавши в файл package.json спеціальне властивість browserslist в кінець файлу:

...

"browserslist": [
    "last 4 versions"
  ]

Додамо відстеження зміни в файлах стилі в Таско watch:

function watch(){
    gulp.watch(path.watch.html, njk);
    gulp.watch(path.watch.style, scss);
}

Так само скорегуємо таск за замовчуванням:

exports.default = gulp.series(
    gulp.parallel(njk, scss),
    gulp.parallel(browsersync, watch)
);

Тепер можна запустити збірку. І якщо ми все правильно зробили, то всі стилі повинні застосовуватися на сайті, і при модифікації будь-якого scss файлу в пвпке ./src/assets/css/, браузер буде перевантажуватися автоматично.

Gulp і webpack. Робота зі скриптами

Для роботи з js скриптами ми будемо використовувати webpack. Webpack – це популярний і гнучкий складальник модулів для javascript. Він вміє вирішувати безліч завдань, як простих, так і складних. Це повноцінний і самостійний інструмент, з великою кількістю доповнень. Але в нашій збірці ми спробуємо подружити webpack і gulp. Для цього будемо використовувати gulp плагін webpack-stream.

І так, як зазвичай, у файлі projectСonfig.json задамо налаштування шляхів для скриптів. Розділ src:

"script": [
    "/assets/js/app.js"
]

Розділ dist:

"script": "/assets/js/"

Як бачимо, вихідний файл знаходиться по шляху src / assets / js / app.js, а компілюватиметься скрипти будуть в папку dist/assets/js/.

У gulpfile.js задаємо масиви з шляхами:

path.src.script[0] = path.src.srcPath + path.src.script[0];

path.dist.script = path.dist.distPath + path.dist.script;

path.watch.script = [];
path.watch.script[0] = path.src.script[0].replace( path.src.script[0].split('/').pop(), '**/*.js' );

В результаті отримуємо:

  • Вхідний файл: ./src/assets/js/app.js
  • Вихідна директорія: ./dist/assets/js/
  • Файли для відстеження: ./src/assets/js/**/*.js

Після цього встановлюємо потрібні плагіни:

npm i webpack-stream webpack gulp-plumber gulp-uglify babel-loader @babel/core @babel/preset-env --save-dev

Розглянемо кожен плагін:

  • webpack-stream — gulp плагін для роботи з webpack
  • webpack — сам бандлер
  • gulp-plumber — спеціальний gulp плагін для відстеження помилок
  • gulp-uglify — плагін для стиснення скриптів
  • babel-loader, @babel/core, @babel/preset-env — набір плагінів для сумісності для старих браузерів

Підключаємо плагіни:

const webpackStream = require('webpack-stream');
const webpack = require('webpack');
const plumber = require('gulp-plumber');
const uglify = require('gulp-uglify');

Описуємо таск для роботи зі скриптами. Для початку створюємо об’єкт для конфігурації webpack:

const webpackConf = {
    mode: isDev() ? 'development' : 'production',
    devtool: isDev() ? 'eval-source-map' : false,
    optimization: {
        minimize: false
    },
    output: {
        filename: 'app.js',
    },
    module: {
        rules: []
    }
}

Тут визначаємо в якому режимі працюємо, включаємо source maps в dev режимі і задаємо вихідний файл app.js.

Дале підключаємо babel в прод режимі:

if(isProd()){
    webpackConf.module.rules.push({
        test: /\.(js)$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader'
    });
}

На цьому не будемо детально зупиняється, єдине що ще потрібно – це створити файл .babelrc з таким вмістом:

{
    "presets": [
        "@babel/preset-env"
    ]
}

І нарешті, створюємо сам таск:

function script(){
    return gulp.src(path.src.script)
        .pipe(plumber())
        .pipe(webpackStream(webpackConf, webpack))
        .pipe(gulpif(isProd(), gulp.dest(path.dist.script)))
        .pipe(gulpif(isProd(), uglify()))
        .pipe(rename({ suffix: '.min' }))
        .pipe(gulp.dest(path.dist.script))
        .pipe(browserSync.reload({stream: true}))
}

Тут все подібно, як і з таском зі стилями. Вмикаємо відображення помилок, запускаємо webpack, стискаємо файл в прод режимі, додаємо суфікс min і перенавантажуємо браузер.

Додамо файли для відстеження в функцію watch:

…

gulp.watch(path.watch.script, script);

…

Далі змінюємо таск за замовчуванням:

exports.default = gulp.series(
    gulp.parallel(njk, scss, script),
    gulp.parallel(browsersync, watch)
);

Створюємо файл app.js. Підключаємо в шаблоні _default.html файл app.min.js перед закривається тегом body:

…

<script src="assets/js/app.min.js"></script>
</body>
</html>

На цьому настройка gulp завдання для роботи зі скриптами закінчена.

Gulp imagemin. Стиснення зображень

Далі ми реалізуємо можливість для роботи з зображеннями за допомогою плагіна imagemin. Цей плагін призначений для стиснення і оптимізації зображень різних форматів.

Задамо настройки для шляхів до зображень. В розділ src додамо:

"image": [
    "/assets/img/**/*.*"
]

В розділ dist:

"image": "/assets/img/"

Створюємо масиви налаштувань в gulpfile.js:

path.src.image[0] = path.src.srcPath + path.src.image[0];
path.src.image[1] = "!" + path.src.image[0].slice(0, -6) + "svgIcons/*.svg";

path.dist.image = path.dist.distPath + path.dist.image;

path.watch.image = [];
path.watch.image[0] = path.src.image[0];
path.watch.image[1] = "!" + path.src.image[0].slice(0, -6) + "svgIcons/*.svg";

Отримуємо такий масив:

  • Вхідні файли: ./src/assets/img/**/*.*, !./src/assets/img/svgIcons/*.svg
  • Вихідна директорія: ./dist/assets/img/
  • Файли для відстеження: ./src/assets/img/**/*.*, !./src/assets/img/svgIcons/*.svg

Тут ми виключаємо папку svgIcons, яка призначена для генерації svg спрайтів. До цього ми повернемося трохи пізніше. Встановлюємо необхідні плагіни:

npm i gulp-newer gulp-imagemin imagemin-jpeg-recompress imagemin-pngquant --save-dev

Розглянемо кожен плагін:

  • gulp-newer — запускають завдання тільки для тих файлів, які змінилися
  • gulp-imagemin — плагін для стиснення зображень
  • imagemin-jpeg-recompress — плагін для оптимізації jpeg зображень
  • imagemin-pngquant — плагін для оптимізації png зображень

Підключаємо плагіни:

const newer = require('gulp-newer');
const imagemin = require('gulp-imagemin');
const imageminJpegRecompress = require('imagemin-jpeg-recompress');
const pngquant = require('imagemin-pngquant');

Створюємо таск для стиснення зображень:

function imageMin(){
    return gulp.src(path.src.image)
        .pipe(newer(path.dist.image))
        .pipe(imagemin([

            imageminJpegRecompress({
                progressive: true,
                min: 70, max: 75
            }),

            pngquant({
                speed: 5,
                quality: [0.6, 0.8]
            }),

            imagemin.svgo({
                plugins: [
                        { removeViewBox: false },
                        { removeUnusedNS: false },
                        { removeUselessStrokeAndFill: false },
                        { cleanupIDs: false },
                        { removeComments: true },
                        { removeEmptyAttrs: true },
                        { removeEmptyText: true },
                        { collapseGroups: true }
                ]
            })

        ]))
        .pipe(gulp.dest(path.dist.image))
}

Gulp webp. Конвертація зображень в webp формат

Далі створимо таск, який конвертує всі зображення в webp формат. Це робиться з метою оптимізації швидкості завантаження сайту. Для цього встановимо плагін gulp-webp:

npm i gulp-webp --save-dev

Підключимо цей плагін:

const webp = require('gulp-webp');

Створюємо таск для конвертації зображень в webp:

function webConverter(){
    return gulp.src(path.dist.image + '**/*.{png,jpg,jpeg}')
        .pipe(webp())
        .pipe(gulp.dest(path.dist.image))
}

У цьому таску в якості вхідних файлів ми беремо зображення в папці dist/img, перетворюємо в webp формат і зберігаємо в цю ж папку.

Тепер ми об’єднаємо два таска: спочатку виконуємо стиснення зображень, потім конвертацію і перезавантажуємо браузер після виконання цих двох завдань:

const image = gulp.series(imageMin, webConverter, (done) => {browserSync.reload(); done();});

Далі змінюємо таск за замовчуванням:

exports.default = gulp.series(
    gulp.parallel(njk, scss, script, image),
    gulp.parallel(browsersync, watch)
);

Також встановимо відстеження за зображеннями в вихідної папці:

function watch(){
    gulp.watch(path.watch.html, njk);
    gulp.watch(path.watch.style, scss);
    gulp.watch(path.watch.script, script);
    gulp.watch(path.watch.image, image);
}

Gulp fonts. Робота зі шрифтами

Наступна можливість, яку хотілося б реалізувати в нашій збірці – це робота зі шрифтами. На сьогоднішній день найпопулярнішими форматами шрифтів є woff2 і woff. Саме їх і потрібно підключати в CSS стилях. Для початку визначимо шляхи для роботи зі шрифтами в файлі projectСonfig.json. Розділ src:

"font": [
    "/assets/fonts/**/*.*"
]

Розділ dist:

"font": "/assets/fonts/"

Визначаємо масив для настройки шляхів шрифтів:

path.src.font[0] = path.src.srcPath + path.src.font[0];
path.src.font[1] = "!" + path.src.font[0].slice(0, -6) + "src/*.*";

path.dist.font = path.dist.distPath + path.dist.font;

path.watch.font = [];
path.watch.font[0] = path.src.font[0];
path.watch.font[1] = "!" + path.src.font[0].slice(0, -6) + "src/*.*";

Отримуємо:

  • Вхідний файл: ./src/assets/fonts/**/*.*, !./src/assets/fonts/src/*.*
  • Вихідна директорія: ./dist/assets/fonts/
  • Файли для відстеження: ./src/assets/fonts/**/*.*, !./src/assets/fonts/src/*.*

Як бачимо, вихідні шрифти будуть копіюватися з папки ./src/assets/fonts/ в каталог ./dist/assets/fonts/. Так само ми виключили каталог src в папці з вихідними шрифтами.

Дуже часто виникає задача конвертувати шрифти застарілих форматів в сучасні. Це завдання досить нудна, тому ми автоматизуємо конвертацію за допомогою gulp. Саме в папці src будуть збережуться шрифти старих форматів, а перетворювати їх будемо в формати woff2 і woff і зберігати в папку з вихідними шрифтами.

Для початку створимо задачу, яка конвертує шрифт ttf в woff2 і woff. Нам знадобляться два плагіна: gulp-ttf2woff2 і gulp-ttf2woff. Встановлюємо їх:

npm i gulp-ttf2woff gulp-ttf2woff2 --save-dev

Підключаємо ці плагіни:

const ttf2woff = require('gulp-ttf2woff');
const ttf2woff2 = require('gulp-ttf2woff2');

Далі описуємо таски для перетворення шрифтів:

function ttf2woff2Converter(){
    return gulp.src(path.src.font[0].slice(0, -6) + "src/*.ttf")
        .pipe(ttf2woff2())
        .pipe(gulp.dest(path.src.font[0].slice(0, -6)));
}

function ttf2woffConverter(){
    return gulp.src(path.src.font[0].slice(0, -6) + "src/*.ttf")
        .pipe(ttf2woff())
        .pipe(gulp.dest(path.src.font[0].slice(0, -6)));
}

Обідняємо ці таски, виконавши один за одним:

const fontsConvert = gulp.series(ttf2woff2Converter, ttf2woffConverter);

Після цього експортуємо функцію:

exports.fontsConvert = fontsConvert;

І так, щоб шрифти з розширенням ttf конвертувати в woff2 і woff, необхідно ввести команду:

npm run dev fontsConvert

Після цієї команди все ttf шрифти c каталогу src перетворюються в сучасні формати і скопійовано в папку /src/ assets/fonts.

Тепер реалізуємо конвертацію з формату otf. Для цього ми спочатку перетворимо формат otf в ttf, збережемо в папку src, ну а далі, як на прикладі вище конвертуємо в потрібні формати. Для цього знадобиться плагін fonter. Встановлюємо його:

npm i gulp-fonter --save-dev

Підключаємо:

const fonter = require('gulp-fonter');

Описуємо таск для конвертації:

function otf2ttf(){
    return gulp.src(path.src.font[0].slice(0, -6) + "src/*")
        .pipe(fonter({
            formats: ['ttf']
        }))
        .pipe(gulp.dest(path.src.font[0].slice(0, -6) + "src"));
}

Вносимо зміни в значення fontsConvert:

const fontsConvert = gulp.series(otf2ttf, ttf2woff2Converter, ttf2woffConverter);

Таким чином всі шрифти в форматі otf і ttf перетворюються в потрібні формати. Далі створимо таск, який скопіює ці шрифти в папку dist:

function font() {
    return gulp.src(path.src.font)      
        .pipe(gulp.dest(path.dist.font))
        .on('end', browserSync.reload);
};

Відредагуємо таск за замовчуванням:

exports.default = gulp.series(
    gulp.parallel(njk, scss, script, image, font),
    gulp.parallel(browsersync, watch)
);

Настроєм відстеження за файлами в папці зі шрифтами:

function watch(){
    gulp.watch(path.watch.html, njk);
    gulp.watch(path.watch.style, scss);
    gulp.watch(path.watch.script, script);
    gulp.watch(path.watch.image, image);
    gulp.watch(path.watch.font, font);
}

Таким чином, при зміні файлів в каталозі src / assets / fonts (або вручну, або в результаті конвертації), запускається таск font, який скопіює шрифти в папку dist / assets / fonts.

Gulp clean. Очищення папки dist

Створимо простий таск, який очищає папку dist. Запускати ми його будемо кожен раз при запуску нашої збірки. Для цього підключимо npm плагін del:

npm i del --save-dev

Підключаємо його:

const del = require('del');

Створюємо таск clean:

function clean(){
    return del([path.dist.distPath]);
}

У дефолтному таску викликаємо очищення перед усіма іншими завданнями:

exports.default = gulp.series(
    gulp.parallel(clean),
    gulp.parallel(njk, scss, script, image, font),
    gulp.parallel(browsersync, watch)
);

Результат

На цьому поки все. Ми розібрали основи роботи з Gulp 4, розглянули приклади використання, створили свою збірку для верстки сайту. У подальших статтях ми будемо її доповнювати і модифікувати. Подивитися і завантажити вихідні збірки можна з сховища .

Коментарі

Залишити відповідь

Натискаючи на кнопку, ви погоджуєтесь з умовами обробки персональних даних