Gulp - сборщик проектов, написанный на языке программирования Javascript. Предназначен для автоматизации типовых задач, возникающих при работе с проектом (копирование, преобразование, компиляция файлов и многое другое).
В данной статье я рассмотрю настройку gulp для проекта, состоящего из двух частей - тестовый (app-vue.loc) и продакшн (vue.loc). Создавать/изменять файлы, настраивать сборщик будем на тестовом, а копироваться и собираться все будет на продакшн. В статье все отражено как есть со всеми путями к локальным проектам.
Программное окружение:
- Windows 10;
- OpenServer (Apache 2.4, PHP 7.4, MariaDB 10.1);
- PHPStorm;
- GIT.
Подготовка рабочего пространства
Для установки gulp и настройки сборщика необходим менеджер пакетов npm, который идет в составе Node.js. Поэтому качаем node.js с офф. сайта и устанавливаем его как обычную программу.
Далее, для работы потребуется рабочая среда: Visual Studio, PHPStorm, WebStorm и т.д. Я использую, по большей части, PHPStorm. Качаем то, что по душе и устанавливаем.
Подготовка проекта
Структура проекта
Для начала создадим такую структуру проекта:
-vue-app.loc
--index.html
--main.js
Здесь всего два файла: точка входа index.html и основной файл со скриптами main.js, в нем будут подключаться библиотеки с помощью системы сборки.
Настройка сборщика
После того как убедились, что Node.js установлен и все работает, открываем терминал и вводим следующую команду для инициализации проекта:
npm init
Нам будут заданы вопросы по проекту. Можем заполнить поля либо пропустить, это не принципиально. Можно будет дозаполнить в файле package.json.
Установка Jquery
Проект инициализирован! Теперь можно приступать к установке библиотек. Установим Jquery. Вводим в терминал следующую команду:
npm install jquery
В корне проекта будет создана директория node_modules. Ее не нужно трогать, в нее будут сваливаться все необходимые библиотеки.
Далее открываем файл main.js и выписываем туда следующую конструкцию:
const $ = require("jquery");
Такая конструкция подключит закачанный нами jquery в проект с помощью системы сборки, но ее у нас пока нет поэтому работать не будет! Ее настроим чуть позже. Для начала, нужно установить gulp.
Установка gulp
Запускаем следующую команду:
npm install gulp --save-dev
После этого, в файле package.json появится запись о gulp:
Далее создаем в корне проекта файл gulpfile.js. В этом файле мы определим логику работы сборщика. Пишем следующий код в файл:
const gulp = require("gulp");
gulp.task("copy-html", () => {
return gulp.src("./app/src/index.html")
.pipe(gulp.dest(dist));
});
Внутри блока gulp.task мы описываем задачу, которая будет выполняться. В данном случае, будет скопирвоан файл index.html из указанного места в другое указанное место. В принципе, можно это по тестировать и по вводить команду gulp copy-html в терминал попутно меняя содержимое файла index.html. Таким образом, мы увидим, что команда отрабатывает корректно, в противном случае, искать ошибку!
Установка модулей для gulp
1. Browserify
Модуль, позволяющий использовать конструкции require('modules') и проводить сборки зависимостей.
Документация - ссылка.
Устанавливаем его через терминал в режиме разработки:
npm install browserify --save-dev
2. Vinyl-source-stream
Обеспечивает наилучшее взаимодействие browserify с gulp.
Документация - ссылка.
Устанавливаем в режиме для разработки:
npm install vinyl-source-stream --save-dev
Далее, приводим файл gulpfile.js к следующему виду:
const gulp = require("gulp");
const source = require('vinyl-source-stream');
const browserify = require('browserify');
const dist = "C:/OpenServer/domains/vue.loc/admin";
//Копирует index.html, с которым мы работаем
gulp.task("copy-html", () => {
return gulp.src("./app/src/index.html")
.pipe(gulp.dest(dist));
});
//Собирает js-файл из main.js. В Последнем же будут прописаны директивы для сборки типа require.
//Конечный файл будет помещен по указанному адресу в константе dist
gulp.task("build-js", () => {
return browserify('./app/src/main.js').bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest(dist))
});
В итоге, мы имеем 2 задачи:
- Копирование
index.htmlв директориюadminна проде. - Сборка
bundle.jsна основеmain.jsи отправка его в директориюadminна проде.
В качестве проверки делаем следующее:
- Приводим
index.htmlк следующему виду:<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <h1>Hello World</h1> <script src="bundle.js"></script> </body> </html> - Добавялем в
main.jsпростой скрипт для плавного исчезновения заголовкаh1. Окончательный видmain.jsдолжен быть таким:const $ = require("jquery"); $('h1').fadeOut('slow'); - Запускаем две команды в терминале:
gulp guild-js gulp copy-html
После этого должен собраться файл bundle.js и поместиться в директорю C:/OpenServer/domains/vue.loc/admin вместе с файлом index.html. Открываем страницу Index.html в директории admin и видим как заголовок исчезает.
Но если посомтреть исходный код и сам файл bundle.js то видно, что он громоздкий и сложно разобраться где какой модуль и где наш код подключен.
Поэтому можно для разработки сделать файлы раздельными, для этого прописываем в файле gulpfile.js для browserify такой параметр - {debug: true}.
return browserify('./app/src/main.js', {debug: true}).bundle()
В итоге, имеем уже такую структуру:
3. Установка babelify
Сам Babel нужен для трансормации js-кода новых стандартов в более старые для поддержки старыми браузерами, а babelify позволяет взаимодействовать Babel с gulp.
Документация Babel - ссылка.
Документация babelify - ссылка.
Установка через терминал для режима разработки:
npm install --save-dev babelify @babel/core @babel/preset-env
babelify установлен. Приводим задачу сборки bundle.js в файле gulpfile.js к следующему виду:
//Собирает js-файл из main.js, в котором мы пропишем директивы сбора, переименовывает его и помещает по указанному адресу
gulp.task("build-js", () => {
return browserify('./app/src/main.js', {debug: true})
.transform("babelify", {presets: ["@babel/preset-env"], sourceMaps: true})
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest(dist))
});
Таким образом, прежде чем собираться, наш файл bundle.js к старому формату JavaScript для поддержки старыми браузерами.
4. Установка gulp scss. Работаем со стилями.
Компилирует scss в css
Документация - ссылка.
Запускаем в терминале следующую команду установки:
npm install gulp-sass --save-dev
Пакет установлен, далее, создаем директорию scss в директории src и добавляем файл style.scss. Архитектура приложения должна иметь следующий вид:
Добавляем в style.scss небольшое правило:
h1 {
color: red;
}
Теперь добавим новую задачу для gulp в файле gukpfile.js также добавив константу с подключением gulp-sass в начале файла:
const gulp = require("gulp");
const source = require('vinyl-source-stream');
const browserify = require('browserify');
const sass = require('gulp-sass');
.../*Старый неизменный код*/...
gulp.task("build-sass", () => {
return gulp.src('./app/scss/style.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(dist));
});
Тестируем запуская поочередно:
gulp build-sass
gulp copy-html
gulp build-js
Все должно собраться и на странице админки должен пропадать уже красный заголовок
Доработка проекта
- Добавляем две директории в директорию
app-apiиassets; - Дорабатываем
gulpfile.js, чтобы он также копировал все файлы из директорий api и assets в проект. Добавляем такие задачи в файл:gulp.task("copy-api", () => { return gulp.src('./app/api/**/*.*') .pipe(gulp.dest(dist + "/api")); }); gulp.task("copy-assets", () => { return gulp.src('./app/assets/**/*.*') .pipe(gulp.dest(dist + "/assets")); }); - Добавляем в директорию
apiфайлapi.phpи добавляем простой код для тестирования:<?php echo "Hello world!"; - Запускаем
gulp copy-apiи убеждаемся, что в основной проект в директориюadmin/apiскопировался файлapi.php.
Автоматизируем gulp
Добавляем в конец файла gulpfile.js такой таск:
gulp.task("watch", () => {
gulp.watch('./app/src/index.html', gulp.parallel('copy-html'));
});
В двух словах: когда будет изменяться файл index.html, будет запускаться метод parallel, который запусти copy-html и скопирует файл в проект.
Теперь, запускаем gulp watch и система будет отслеживать изменения в файле index.html и при сохранении файла копировать его в проект.
Делаем все тоже самое для остальных файлов проекта, добавляем в gulpfile.js следующие элементы для watch:
gulp.task("watch", () => {
gulp.watch('./app/src/index.html', gulp.parallel('copy-html'));
gulp.watch('./app/api/**/*.*', gulp.parallel('copy-api'));
gulp.watch('./app/assets/**/*.*', gulp.parallel('copy-assets'));
gulp.watch('./app/src/**/*.js', gulp.parallel('build-js'));
gulp.watch('./app/scss/**/*.scss', gulp.parallel('build-sass'));
});
Примечание. Чтобы остановить слежение за файлами достаточно нажать ctrl + C.
Теперь делаем так, чтобы мы могли собрать все файлы одной командой build, добавляем в gulpfile.js следующее:
gulp.task("build", gulp.parallel('copy-html', 'copy-api', 'copy-assets', 'build-js', 'build-sass'));
Можно максимально автоматизировать формирование проекта на лету сделав так, чтобы проект билдился и вставал в режим слежки одной командой gulp. Добавляем в gulpfile.js следующее:
gulp.task("default", gulp.parallel("watch", "build"));
Теперь просто пишем в терминал gulp и можем спокойной работать с проектом. Тестируем, вносим изменения в разные файлы, все будет отражаться на реальном проекте.
На этом подготовка проекта и первоначальная настройка сборщика закончена!
Прочие вопросы
1. Как подключить файл css/scss из установленной библиотеки в node_modules.
Пока я это делаю так:
gulp.task("build-sass", () => {
return gulp.src(['./src/scss/style.scss', './node_modules/magnific-popup/dist/magnific-popup.css'])
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer({browsers: ['last 2 version', '> 2%', 'firefox 15', 'safari 5', 'ie 6', 'ie 7', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4']}))
.pipe(gulp.dest(dist + '/css/'))
});
То есть добавляю в массив src дополнительный путь к файлу. Он в dist вывалится отдельным файлом скомпиленым.



