Gulp
Теория: Базовые функции Gulp
В прошлом уроке мы подключили встроенную в пакет Gulp функцию parallel(), которая позволила объединить несколько функций в одну единую задачу.
Помимо parallel() внутри пакета Gulp существует ещё несколько функций, которые будут рассмотрены в этом уроке. Нет нужды расписывать каждую функцию в отдельности, поэтому рассмотрим самые распространённые, которые вы будете использовать в работе. Больше информации про различные функции можно будет найти в документации пакета Gulp, ссылка на которую будет в конце урока.
series()
Функция series() по своему функционалу очень похожа на функцию parallel(), которую мы изучили в прошлых уроках. Но если есть две разные функции, значит у них должны быть отличия? И ответ — да! Отличие заключается в том, как именно будут вызываться функции в рамках задачи. И здесь два подхода:
- Функция
parallel(), как можно понять из названия, выполняет функции параллельно/одновременно. В примере выше функцииsassCompile(),pugCompile()иimagesOptimize()не будут стоять в какой-то очереди или дожидаться окончания друг друга, а начнут работать вместе. Этот подход удобен, если задачи никак друг с другом не связаны и результат одной не зависит от результата другой.
- В противовес параллельному выполнению есть последовательное, которое реализуется функцией
series(). Смысл этой функции в том, что пока не завершилась работа одной функции не начнётся выполнение другой. Это очень важно при использовании множества подзадач, которые напрямую влияют на то, с чем будет работать следующая функция.
На скриншотах стоит обратить внимание на то, когда запускаются задачи. В параллельном выполнении Gulp показывает одновременный запуск всех задач, а при использовании функции series() выполнение новой задачи стартует только после окончания выполнения предыдущей.
src() и dest()
Многие задачи при работе с Gulp связаны с обработкой файлов. Будь то SASS, Pug или иной инструмент, все их необходимо обработать в формат, который понимает браузер. Для этого необходимо указать, какой файл будет обработан и куда его нужно переместить после обработки. За это, в Gulp отвечают две функции:
src()для указания пути к обрабатываемому файлуdest()для указания пути, куда необходимо положить обработанный файл
Особых неожиданностей здесь нет. Эти функции отвечают за обработку путей к файлам и базовому взаимодействию. На самом деле они намного гибче, чем может показаться с самого начала, но остальной функционал используется крайне редко и в больших проектах, например кеширование. Посмотрите на базовый пример операции по копированию файла:
После выполнения задачи файл src/sass/app.scss будет скопирован в директорию build/styles/
layout-project/
├── build/
│ ├── styles/
│ │ └── app.scss
├── src/
│ ├── sass/
│ │ └── app.scss
│ ├── pages/
│ │ ├── index.pug
│ │ ├── sections/
│ │ │ ├── head.pug
│ │ │ └── footer.pug
├── gulpfile.js
├── package.json
└── node_modules/
Сейчас он там не нужен, так как в директорию build попадут уже обработанные файлы, но теперь вы знаете, каким именно способом они туда попадут :)
Обратите внимание, что в примере не вызывается функция done(), как было в прошлых примерах. Это связано с тем, что мы указали ключевое слово return. Подробнее о ключевом слове return вы могли прочитать в курсе введения в программирование.
Globs
В примере выше был указан чёткий путь к файлу, который мы хотим скопировать. Для небольших проектов это может быть достаточно простым и эффективным решением, но, зачастую необходимо обработать не один, а все файлы из определённой директории или даже дерева директорий. К примеру, у нас возможна вот такая структура стилей:
layout-project/
├── src/
│ ├── sass/
│ │ ├── global.scss
│ │ ├── mobile.scss
│ │ ├── desktop.scss
Как корректно обработать три этих файла? Есть два варианта:
- Обработать каждый файл в отдельности
- Обработать все файлы внутри одной функции
С первым вариантом всё просто — создаём три функции, объединяем их в единую задачу и выполняем:
Если всего файла три, то такое решение можно считать нормальным, но не хорошим. Ведь над каждым файлом производится одинаковая операция, а меняется только сам обрабатываемый файл.
Для указания нескольких файлов используются специальные шаблоны путей — Globs. Это небольшой пакет, который преобразует шаблоны в пути и по умолчанию встроен в Gulp. Достаточно изучить пару приёмов, с помощью которых вы сможете выбирать почти любые файлы и в любом количестве.
Первая конструкция — использование звёздочки *, она указывает на то, что надо выбрать всё, что не противоречит указанному в пути. Например, мы можем заменить звёздочкой имя файла в последнем примере и, тогда, Gulp выберет все три файла: global.scss, mobile.scss и desktop.scss
Можно ещё больше упростить процесс копирования файлов. Предположим, что SASS файлы находятся в совершенно разных директориях, а мы хотим сложить их в единую. Необходимо пройтись по всем доступным директориям, проверить наличие там файла с расширением scss/sass и скопировать. Для этого используется специальная конструкция **, которая нацелена на проход по директориям. Например, можно видоизменить код следующим образом:
Теперь при запуске задачи будут проверены все директории внутри src на предмет наличия файла с расширением .scss. Здесь важно отметить, поиск будет производиться не только внутри поддиректорий src, но и в самой директории src. Например будут выбраны следующие файлы:
- src/styles.scss
- src/project/app/styles/app.scss
- src/sass/mobile.scss
и так далее.
Важно: при использовании метода с поиском файлов в различных директориях, при их переносе с помощью функции dest() Gulp сохраняет ту вложенность, которая была. Например, при выполнении прошлого примера файл src/project/app/styles/app.scss окажется по пути build/styles/project/app/styles/app.scss. Это важная особенность, которую стоит помнить для избежания ошибок при работе с проектом.
Это отлично работает, но есть одна существенная проблема — внутри нашего src могут находиться директории, из которых нет необходимости обрабатывать файлы. Например, директории с npm-пакетами. Чтобы уйти от этой проблемы в Globs существует метод исключения директорий, который указывается через знак логического отрицания !. В таком случае нужные пути и исключаемые указываются в виде массива строк. Исключим из копирования директорию src/project:
Важно обратить внимание, что в конце исключаемой директории стоят символы /**. Они говорят о том, что необходимо исключить не только саму директорию, но и все вложенные в неё.
Pipe()
При просмотре последних примеров может возникнуть вопрос: «Что за pipe?». Перейдём к этому методу:
Если не вдаваться в тонкие подробности, то pipe() позволяет связывать потоки чтения и записи друг с другом. Если вернуться к примеру с копированием файлов, то именно с помощью pipe() появляется возможность получить файл и отдать его для последующей обработки функции dest().
Так же будет происходить и при обработке файлов с помощью плагинов, например при компиляции SASS в CSS. Чтобы связать всю цепочку одновременно необходимо использовать pipe().
В контексте работы с пакетом Gulp можно выстроить типичную цепочку, или шаблон, задачи:





