Когда плагин разрастается, то всё тяжелее ориентироваться в нем плюс много времени уходит на передвижение по коду. Конечно, можно расставить закладки, но в них опять же легко запутаться.
В этом случае нам может помочь Gulp (по-русски его зовут "галп или "гальп") - сборщик проектов, скриптов, а также помощник для быстрой минификации файлов, сжатия картинок, автоматизации процессов и много чего другого. С помощью него мы можем писать плагин в нескольких файлах, а затем "склеивать" их в один.
Какие плюсы?
1) Легче и быстрее лазить по коду, если он разросся то нескольких сотен и тысяч
2) Возможность исопльзовать один файл для создания нескольких плагинов. К прмиеру, если в обоих плагинах задействуется вызов при нажатии на кнопку, то мы можем использовать один файл для склейки его сразу в несколько плагинов
3) Можно легко и быстро минифицировать код, чтобы файл плагина весил меньше. В том числе можно сжимать и код стандартных скриптов мейкера.
Плюс если у вас паранойя, что код украдут, "жесткая минификация" изменит названия функций и переменных, и тогда враг, скачавший ваш плагин, замучается в нем разбираться
4) Можно делать отдельные версии для разработки и "деплоя", т.е. размещения проекта. Например, при создании демки автоматически убирать плагины для теста, ускорения разработки типа "дк тулс"
5) Можно сжимать графический файлы одним нажатием
6) Настроив галп один раз, мы его затем можем использовать для других проектов
7) И т.д.
На форуме уже есть
статья Амфи на счет него, но полтора года назад мне она показалась сложноватой для человека "с нуля" из-за путанницы кода "галпа" с кодом "кофескрипта". Поэтому решил написать урок для совсем новичков в этом деле
Инструменты
1) Nodejs - грубо говоря, программа для взаимодействия нашего компьютера с внешними библиотеками, устройствами ввода-вывода. С помощью него мы будем подключать нужные нам плагины как и сам gulp
2) Любой редактор кода. В данном случае я бы отдал предпочтение Visual Code от "майкрософт". В нем есть встроенная консоль, в отличии от того же саблайма.
2. Установка nodejs
1) Переходим на сайт
https://nodejs.org/en/, качаем последнюю версию (Current. Latest features), устанавливаем.
1. Создание Gulp
Установка Gulp'а через Nodejs происходит также, как и установка остальных инструментов через nodejs
1) Открываем в виндоус "выполнить" (в вондоус 10 правой кнопкой по значку "пуска" и далее - "выполнить"
2) Вводим cmd. Нажимаем "enter". Появляется командная строка
3) Теперь нам надо установить Галп на компьютер. Стандартная команда nodejs для этого:
npm install "название пакета" -g
, где:
- npm - команда для обращение к инструменту Node Package Manager ("управление пакетами"),
- install - команда для установки,
- "название пакета" - название нужного нам пакета, в данном случае gulp. Как-то я уже писал про другой пакет Browser sync и, как видим, алгоритм установки одинаков
- -g - команда для установки пакета глобально, то есть в систему компьютера, а не в определенную папку. Команды, которые начинаются с "-" еще называют "флаг"
Посетив сайт "галпа"
https://gulpjs.com/, видим название пакета "gulp-cli" и в итоге у нас получается строчка
npm install gulp-cli -g
Обычно подобную строчку пишут на сайтах всех пакетов, но теперь мы понимаем, что она значит.
3. Создание папки проекта
1) Создаем нужную нам папку, в которой мы будем работать. Для понимания основ пока абстрагируемся от мейкера, и просто создадим пустую папку, назвав ее например "gulp"
2) Переходим в эту папку через командную строку.
Так как по умолчанию путь в командной строке "C:\Users\*имя пользователя*", а наша папка создана скорее всего по-другому пути, то нам следует перейти в нужную нам папку для работы в ней через командную строку
Есть два способа для этого:
а) Переход в папку чисто через командную строку:
1) Сначала вводим "*название диска*:". Например, если папка у нас находится на диске D, то вводим "d:" (без кавычек). Получится что-то типа:
C:\Users\Yuryol>d:
2) Смотрим, какие папки есть на данном диске через команду "dir".
D:\>dir
Нам выведется информация типа:
D:\>dir
Том в устройстве D имеет метку Новый том
Серийный номер тома: 96DC-2439
Содержимое папки D:\
18.01.2019 18:48 <DIR> Games
12.10.2018 12:24 <DIR> save
11.09.2018 21:36 <DIR> SoftwareDistribution
09.01.2019 21:46 <DIR> Yuryol
0 файлов 0 байт
5 папок 148 299 595 776 байт свободно
3) Вводим "cd *название папки или пути*" чтобы перейти в нужную нам папку:
D:\>Yuryol
Снова вводим dir, а потом переходим в нужную папку. Повторяем шаги, пока мы не оказались в нужной папке.
4) Неудобно? Да. Но к счастью после ввода диска через "d:" мы можем сразу ввести общий путь к нашей папки, например:
D:\>cd D:\Yuryol\lesson\Programming\gulp
теперь у нас строчка "D:\Gen\lesson\Programming\gulp>", а значит мы находимся в нужной папке и можем продолжить работать
б) Переход через виндоус:
1) закрываем окно с командной строкой, переходим через проводник к нашей папке "gulp".
2) зажимаем клавишу "шифт" и не отпуская ее кликаем правой кнопкой по папке
3) В контексном меню выбираем "Открыть окно команд". Радуемся! Консоль открылась сразу с нужным нам путем:
D:\Yuryol\lesson\Programming\gulp>
3. Инициализация
1) Для того, чтобы nodejs видел нашу папку, следует ему ей показать. Как говорят умные люди: "инициализировать":
npm init -y
, где:
- npm - команда для обращение к инструменту Node Package Manager ("управление пакетами"),
- init- команда для инициализации,
- -y - команда ("флаг", как мы уже знаем) для пропуска предварительных вопросов. Если мы его уберем, то консолька спросит у нас название проекта, имя автора и т.д. Пока нам это не надо, поэтому на помощь приходит "-y"
Итого у нас выходит команда
D:\Yuryol\lesson\Programming\gulp>npm init -y
2) После инициализации в нашу папку добавляется файл "package.json". Это наш основной файл настройки. Открыв его, мы увидим объект, в котором около десятка элементов.
Здесь нас интересует строка "dependencies". В этом элементе, который сам также будет являться объектом, у нас будут указываться пакеты, которые используются в нашем проекте. Пока здесь пусто, но скоро там появится и "gulp", и многие другие пакеты
3) Помните про флаг "-y"? Если бы мы его не поставили, то например такие элементы как "name" и "author" мы заполняли бы через командную строку, и в файле "package" они бы были соответственно другие. Но некоторые поля,например поле "author" мы также можем заполнить и сейчас, главное не забывать кавычки.
4. Добавление Gulpа в наш проект
1) Как я уже говорил, все пакеты мы устанавливаем однотипно: npm install gulp -g
Однако сейчас нам надо установить gulp в папку, то есть локально, а не глобально, поэтому флаг "-g" нам не нужен.
Также для установки gulp локально, мы пишем "gulp", а не "gulp-cli". Вообще, обычно названия пакетов не отличаются при установке глобально и локально, но тут другой случай. В итоге у нас получается строчка
npm install gulp
Еще один момент: install можно и писать и более коротко, просто "i". Поэтому также мы можем вводить:
npm i gulp
И третий момент. При локальной установке важны флаги "--save-dev" и "-save".
--save — указывает, что пакет войдет в финальный продукт. Пакет будет добавлен в поле "dependencies" в package.json.
--save-dev — указывает что пакет нам нужен для разработке. Пакет будет добавлен в поле "devDependencies" в package.json.
По умолчанию у нас флаг "--save", но "галп" нам нужен только для разработки. Поэтому мы должны написать
npm i gulp --save-dev
Как и в случае с "инсталл", есть сокращенная запись для --save-dev, а именно короткий флаг "-D". Итого наша строчка:
npm i gulp --D
2) После установки галпа у нас появится папка папка node_modules и файл package-lock.json
Папка node_modules содержит кучу пакетов nodejs. Они нужны для быстрой установки пакетов в наш проект
Файл package-lock содержит зависимости этих пакетов друг от друга.
На них мы пока можем не обращать внимание, главное проверьте поле "devDependencies" в package.json. Оно у нас должно быть
"devDependencies": {
"gulp": "^4.0.0"
}
, где "gulp" - название пакета, "^4.0.0" - версия пакета
5. Создание проекта
Создаем два файла, например console.js и main.js, которые нам надо объединить в один.
В main.js пишем например:
let a = 5 + 6
В console.js пишем например:
console.log(a)
6. Написание файла для сборки
Наконец мы переходим к написанию коду и непосредственно сборки проекта:
1) Создаем файл js с названием "gulpfile.js". Название должно быть таким и никак иначе!
2) В нем мы должны подключить галп, поэтому пишем строчку:
const gulp = require('gulp');
Это своего рода экспорт. Мы создаем константу и экспортируем файлы с папки "gulp", который находится у нас в папке "node_modules"
3) Пишем скрипт, который будет брать два файла js и склеивать их в один.
К примеру, если у нас есть два файла console.js и main.js, то мы можем соединить их в один файл, например "plugin.js".
Для этого пишем функцию:
function script() {
return gulp.src(['./console.js', './main.js'])
.pipe(concat('plugin.js'))
.pipe(gulp.dest('./'))
}
, где:
- gulp.src() - метод, в котором мы указываем какие файлы мы должны склеить. Аргумент в них - - массив с путями и названиями этих файлов. "./" - корневая папка, затем следует путь для файла
- .pipe(concat('plugin.js')) - метод для склейки файлов в один. Аргумент 'plugin.js' - название файла, в который склеятся оба плагина
- .pipe(gulp.dest('./')) - метод, который указывает в какую папку нам надо сохранить наш получившийся файл. В данном случае сохраняем в корневую папку
4) Указываем название команды, которую будем вводить для вызовы данной склейки файлов:
gulp.task('plugin', script);
Первый аргумент - название команды для запуска нашей функции. Второй аргумент: название нашей функции. В данном случае она у нас называется "script"
5) Итого наш код вышел таким:
const gulp = require('gulp');
function script() {
return gulp.src(['./console.js', './main.js'])
.pipe(concat('plugin.js'))
.pipe(gulp.dest('./'))
}
gulp.task('plugin', script);
6) Теперь мы можем запустить нашу склейку файлов через команду "gulp *название команды*". В данном случае у нас:
gulp plugin
Мы вводим ее в консоль и вуаля! Получаем ошибку:
D:\Yuryol\lesson\Programming\gulp >gulp plugin
[17:52:32] Using gulpfile D:\Yuryol\lesson\Programming\qw\gulpfile.js
[17:52:32] Starting 'plugin'...
[17:52:32] 'plugin' errored after 12 ms
[17:52:32] ReferenceError: concat is not defined
at script (D:\Yuryol\lesson\Programming\gulp \gulpfile.js:5:16)
at taskWrapper (D:\Yuryol\lesson\Programming\gulp \node_modules\undertaker\lib\set-task.js:13:15)
at bound (domain.js:370:14)
at runBound (domain.js:383:12)
at asyncRunner (D:\Yuryol\lesson\Programming\gulp \node_modules\async-done\index.js:55:18)
at process._tickCallback (internal/process/next_tick.js:150:11)
8. Установка gulp-concat
Если вы видите ошибку: [17:52:32] ReferenceError: concat is not defined
То значит у нас не установлен пакет, в данном случае "concat".
Дело в том, сто команда "concat " - это команда не галпа, а расширения для него "gulp-concat". Поэтому просто устанавливаем этот пакет:
1) Как уже знаем устанавливаем пакет в папку с добавлением в полк "резработка" в package.json:
npm install --D gulp-concat
Да, кстати. Чтоб постоянно не вводить однотипные команды в консоли, мы можем нажимаеть стрелочки "вверх" и "вниз". И тогда команды в консоль будут вписываться сами
2) Подключаем пакет в проект добавив в файл gulpfile.js строчку:
const concat = require('gulp-concat');
3) Теперь наконец-то у нас всё работает!
gulp plugin
И у нас создается файл plugin.js , в котором есть наш код^
console.log(a);
let a = 5+6;
Как известно, переменную let нельзя объявлять ПОСЛЕ вызова, поэтому меняем порядок склейки файлов, чтобы сначала был "main", и только затем "console". И вместо
gulp.src()
пишем:
return gulp.src()
9. Минификация файлов
Для минификации кода у нас есть такой инструмент как gulp-uglify.
1) Делаем привычные вещи: устанавливаем его через
npm install -D gulp-uglify
2) Экспортируем пакет в скрипт:
const uglify = require('gulp-uglify');
3) Добавляем строчку в нашу функцию, которая минимизирует файл.
.pipe(uglify())
Ее надо добавить после объединения файла но ПЕРЕД сохранением:
function script() {
return gulp.src(['./console.js', './main.js'])
.pipe(concat('plugin.js'))
.pipe(uglify())
.pipe(gulp.dest('./'))
}
4) запускаем gulp plugin и видим ошибку:
D:\Yuryol\lesson\Programming\qw>gulp plugin
[21:29:46] Using gulpfile D:\Yuryol\lesson\Programming\qw\gulpfile.js
[21:29:46] Starting 'plugin'...
[21:29:46] 'plugin' errored after 39 ms
[21:29:46] GulpUglifyError: unable to minify JavaScript
Caused by: SyntaxError: Unexpected token: name (a)
File: D:\Yuryol\lesson\Programming\qw\plugin.js
Line: 2
Col: 4
5) Дело в том, что этот пакет не может работать с синткаксисом ES6. Есть два выхода: использовать пакет babel, которые превратит наш код в старенький добрый жаваскрипт без всяких там let:
var a = 5+6;
console.log(a);
Как это делать пока объяснять не будет, можно попробовать самому. Проблема тут в том, что не всегда нам надо переводить новый синтаксис в старый. К примеру, MV работает с новым синтаксисом и например я хочу чтоб и получившийся файл был с новым синтаксисом.
Поэтому мы будем использовать
gulp-uglify-es
10. Минификация файлов с синтаксисом ES6
1) Устанавливаем
npm install -D gulp-uglify-es
2) Добавляем в функцию
const uglify = require('gulp-uglify-es').default;
3) Запускаем gulp plugin и видим что на выходе у нас получился минифицированный файл plugin.js
let a=11;console.log(a);
4) Мы можем сделать минификацию еще жестче. Для этого передаем аргументом в методе минификации объект { toplevel: true }
.pipe(uglify({ toplevel: true }))
5) Теперь код стал совсем короткий:
console.log(11);
uglify настолько умный, что высчитал ненужность переменной для такой операции, сразу сосчитал значение переменной и сразу закинул его в консоль. Более того, uglify также сократил бы название переменной до одной буквы, если бы наша переменная называлась более длинным словом. Можете с этим поэкспериментировать сами
11. Автоматический запуск заданий
Согласитесь, неудобно постоянно запускать в командной строке gulp plugin . Поэтому мы будем использовать gulp-watch, чтобы склейки плагина происходила всегда, когда изменяется какой-либо файл с типом .js
1) Устанавливаем gulp-watch через npm install -D gulp-watch, а затем подключаем его в скрипт через const watch = require('gulp-watch');
2) Пишем после всего скрипта отдельный "таск"
gulp.task('watch', function(){
gulp.watch('./*.js', gulp.parallel('plugin'));
})
, где
- gulp.task() - вызов таска
- 'watch' - первый аргумент, означающий название команды для запуска. Можем назвать ее как нам захочется
- gulp.watch() - метод для слежением за файлами
- './*.js' - название файлов. Здесь у нас написан сначала путь до файлов "./", а затем ВСЕ файлы с разрешением .js - "*.js"
- gulp.parallel('plugin') - метод в котором арге=ументом передаем название таска, который мы хотим запустить. в нашем случае это plugin. Если у нас несколько заданий, ты можем их перечислять через запятую, напрмиер: gulp.parallel('plugin', 'minImg')
3) Итого у нас получится следующий код:
const gulp = require('gulp');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify-es').default;
const watch = require('gulp-watch');
function script() {
return gulp.src()
.pipe(concat('plugin.js'))
.pipe(uglify({ toplevel: true }))
.pipe(gulp.dest('./'))
}
gulp.task('plugin', script)
gulp.task('watch', function(){
gulp.watch('./*.js', gulp.parallel('plugin'));
})
ИТОГО
Итого с помощью gulp мы можем склеивать несколько файлов в один. Подобная модульность облегчает разработку плагинов, если в них содержатся функции совершенно разного функционала: отслеживание нажатий клавиш, худ-бар и прочее. Кроме того легко минифицировать данный файл и перевести код в старый синтаксис js
домашнее задание:
1) Применить знания на практике: настроить gulpfile для rpg maker mv, чтоб он склеивал файлы с разрешением .js, находящиеся в созданной папке "devJs" в корне папки с игрой и создавал один файл в \js\plugins
2) Сделать чтоб создавалось два файла: минифицированный и не минифицированный. Подсказка: поможет пакет 'gulp-rename'
3) Сделать чтоб также создавался третий файл, в котором код ES6 переведен в старый формат (в этом нам поможет babel)
4) Создать задание для минификации всех картинок папки img мейкера ('gulp-imagemin')
5) gulp не удаляет файлы , а пишет поверх. Поэтому например если вдруг мы удалим картинку, то копия картинке в папке с минифицированными картинками останется. Создайте задания для очищения папки с минифицированными картинками перед тем как туда что-то записывать