Технологии нужны для автоматизации процессов, поэтому в этом уроке мы учимся работе со скриптам в Нпме и Галпу
Если вы не знаете Джаваскрипт, то в курсе по Реакту пройдите третий урок, «Джаваскрипт для начинающих». Он открытый. Да и остальные тоже полезными будут!
С Нпмом вы уже знакомы по четырнадцатому уроку с Постцсс и знаете про работу с пакетами.
Пакеты бывают двух типов: исполняемые (или бинарники) и подключаемые. Нас интересуют первые — вторые понадобятся в курсе по Реакту.
В Нпме полно пакетов, которые можно запустить в Терминале. Ключевое отличие от Хоумбрю или другого системного пакетного менеджера в том, что почти всегда пакеты в Нпме написаны на Джаваскрипте, а поэтому благодаря Ноде запускаются на любой системе без особых правок.
Обычно эти пакеты имеют постфикс -cli
(command line interface).
Кстати, вы же не забыли, что говоря Нпм, мы подразумеваем базу Нпма, с которой мы будем работать через Ярн?
Примеры?
- postcss-cli — уже знакомый ПостЦСС,
- html-minifier — минификатор ХТМЛ,
- uglify-js — минификатор и оптимизатор Джса,
- pa11y — тестировщик a11y,
- stylelint — линтер стилей,
- и даже git-open — команда для открытия Гитхаба или других сервисов из консоли.
Линтер, кстати, это анализатор кода на предмет проблем
Окей, эти пакеты мы и так умеем запускать через yarn postcss ...
или yarn pa11y ...
, а причём тут Нпм?
В нпмовском package.json
есть поле scripts
: это Джаваскриптовский объект, где можно написать скрипты, которые вы потом будете запускать через yarn run ...
.
Пример:
{
"name": "erodionov.ru",
"scripts": {
"minify:html": "html-minifier --input-dir src --output-dir dist",
"minify:css": "csso --input src/styles.css --output dist/styles.css",
"minify": "yarn run minify:html && yarn run minify:css",
"lint": "stylelint src"
}
}
Зачем это вообще нужно?
Во-первых, команды можно комбинировать через &&
— вместо 10 команд вы можете запускать одну. На самом деле, оператор &&
— системный, поэтому это не особо аргумент.
Во-вторых, эти скрипты работают как альясы: вместо того, чтобы писать огромные команды с кучей флагов, вы всё сводите к yarn run X
. Вот это действительно удобно!
Но что делать, если команд становится очень много? Штук 50 не очень хочется поддерживать, верно? Для этого существует Галп.
Галп это утилита, которая автоматизирует воркфлоу (рабочий процесс) через таски (задачи).
Часто звучит мысль о том, что Галп не нужен — во фронтэнде это правда, почти во всех задачах его заменил Вебпак (мы рассматриваем его в курсе по Реакту), а с остальным справляются Нпм-скрипты. Тем не менее, в вёрстке нет Вебпака, поэтому тут спокойно используют Галп.
Таски (task
) в Галпе очень простые: на вход (in
) подаётся исходник (src
), мы его преобразовываем (pipe
), на выходе (out
) мы получаем результат (dest
).
Галп, кстати, работает на своих плагинах, поэтому вам нужны специальные версии: модуль csso
не подойдёт, нужен gulp-csso
). То же самое с Постцссом: нужен gulp-postcss
. Гуглите gulp [нужный модуль]
.
Смотрите, вот как это выглядит в коде:
// gulpfile.js
const gulp = require("gulp"); // подключаем Галп как модуль
const minifycss = require("gulp-csso");
const postcss = require("gulp-postcss");
// плагины для ПостЦСС
const autoprefixer = require("autoprefixer");
const cssnext = require("cssnext");
// объявляем таск с названием "styles"
// первым аргументом — название таска,
// вторым — функция, которая возвращает (`return`),
// обработанным
gulp.task("styles", function() {
return gulp
.src("src/styles/*.css") // через .src() передаём путь до исходника
.pipe(postcss([cssnext(), autoprefixer()])) // через .pipe() вызываем плагин как функцию
.pipe(minifycss()) // и ещё раз
.pipe(gulp.dest("build/styles")); // в финальном пайпе через gulp.dest() указываем куда сложить результат
});
В документации Галпа есть крутые рецепты, описание АПИ, и плагины. А я попробую ответить на возникшие вопросы.
Во-первых, gulp-cli
должен быть установлен в проекте.
Во-вторых, как и любой исполняемый пакет — yarn gulp [название таска]
.
Вторым аргументом функции .task()
передайте массив других тасков, а не функцию. Пример есть на главной странице Галпа.
gulp.task("build", ["styles", "scripts", "images"]);
Важно: все таски будут запускать параллельно, а не последовательно.
Ответ в документации: Running tasks in series, i.e. Task Dependency
Можно воспользоваться gulp.watch
по аналогии с gulp.task()
: первым аргументом название (например, 'watch-js'
), вторым — массив из тасков.
Галп будет держать процесс открытым и запускать таски, если что-то изменилось в исходниках.
Это можно исправить инкрементальным обновлением (incremental update) через gulp-watch
, рецепт есть, опять же, в документации: Rebuild only files that change.
Для начала вам нужно разделить проект на две директории: src
и build
. В первой будут исходники, во второй — обработанные файлы.
Не забудьте, что build
не должна быть в репозитории — воспользуйтесь .gitignore
.
Вот задания:
- перенесите работу с ПостЦСС в Галп,
- подключите какой-нибудь оптимизатор картинок,
- подключите минифайеры ХТМЛ и ЦСС,
- подключите Стайлинт (конфигом возьмите stylelint-config-standard) — вы должны знать об ошибках,
- объедините это под таском
build
, - а для собственного удобства заведите таск
watch
.
Чтобы было проще работать с Джаваскриптом, поставьте в редактор Преттир — это форматтер кода — и Еслинт (с конфигом eslint-config-recommended) — это валидатор кода, он будет подсвечивать ошибки чтобы вы их исправляли ещё до запуска Галпа Нодой.
В этом уроке мы разобрались с автоматизацией процессов через Нпм-скрипты и Галп.
Вопреки слухам, Галп живее всех живых и всё ещё помогает верстальщикам спасаться от боли ручной работы.
Кстати, есть ещё один популярный таск раннер — Грант. Галп настраивается кодом на Джаваскрипте, а Гранта программируется конфигами. Плюс работает медленнее (потому что Галп работает с памятью, а Грант с файлами), ну и заброшен сообществом давным-давно.