Gulp не является. Понимаем и работаем с gulp. Установка и настройка gulp-rename

13 декабря 2017 в 17:40

Понимаем и работаем с gulp

  • JavaScript

Всем привет. Если вы связаны хоть как-то с JS, вы наверняка слышали о таком приложении как gulp . А возможно даже и использовали. По своему опыту могу сказать, что «въехать» в то, как с ним работать бывает сложно, хотя ключ к пониманию лежит на поверхности. Поэтому и публикую этот материал, надеясь, что он станет полезным.

Так же, на основе данного материала был снят видеоролик, так что можете выбирать, в каком виде потреблять.


Если сравнить gulp с другими популярными системами сборки, то это как сравнивать готовый квадрокоптер по типу “купил и полетел”, и набор для самостоятельной сборки дрона. Да, взлетите вы только на следующий день, но зато у ваших руках больше гибкости и контроля, особенно если у вас нестандартная задача.

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

Зайдем издалека. В экосистеме nodejs, существует такое понятие, как потоки , или stream. Из-за сложности перевода, потоками так же называются нити или threads многопоточной программы. В нашем же случае, поток - это объект, представляющий потоковые данные, и является совершенно иным понятием.

Так вот эти потоки предлагают удобный интерфейс для асинхронной работы с данными. Всем процессом чтения/записи занимается движок ноды, а мы имеет только соответствующие колбеки, когда появилась новая порция данных, когда произошла ошибка, когда поток закончился и т.п. Таким образом достигается эффективность ввода/вывода при минимальных затратах со стороны программиста.

Const fs = require("fs"); const input = fs.createReadStream("myfile"); input.on("data", (chunk) => { console.log(chunk); }); input.on("end", () => { console.log("file is read"); });
Потоками в nodejs может быть практически все, начиная от файлов или строк заканчивая сокетами. Например, в известном фреймворке Express, HTTP запрос и ответ являются ни чем иным, как потоками. Потоки могут быть только на чтение, только на запись или и то и другое.

Есть у потоков одна полезная функция: их можно складывать между собой у цепочку, которая называется pipe. Таким образом, мы можем объединить несколько потоков между собой, и управлять им как одним целым. Выход одного потока идет на вход следующему и так до конца. Как можно догадаться из перевода слова pipe, это очень похоже на трубопровод.

Это позволяет определить нужный поток данных (опять сложность перевода. Здесь имеется в виду flow, или течение) прямо здесь и сейчас не дожидаясь, когда данные станут доступны.

Например, вот так вот мы можем определить, что мы хотим отдать как результат, а “как” отдавать уже занимается сам движок.

Const fs = require("fs"); const express = require("express"); var app = express(); app.get("/", function (req, res) { fs.createReadStream("myfile") .pipe(res); }); app.listen(3000);
Обратите внимание, что обработчик запроса завершается до того, как файл даже откроется - остальное берет на себя движок ноды.

Gulp построен на аналогичном подходе. Это его преимущество, но это и его недостаток. Недостатком, как минимум, можно назвать из-за возникающей путаницы, поскольку gulp использует другие, похожие, но несовместимые потоки. Gulp плотно работает с файловой системой, поэтому он и использует потоки, которые представляют не столько поток данных, сколько отдельные виртуальные файлы, каждый со своим содержимым.

Если вы когда-нибудь слышали о vinyl - это как раз и есть реализация потоков, которые используют в gulp. Если мы возьмем стандартную задачу для галпа, и посмотрим что там внутри, то обнаружим, что на каждый вызов события data к нам приходит объект file, который и содержит всю необходимую информацию: имя файла, путь к файлу, рабочая директория и конечно же, его содержимое.

Const gulp = require("gulp"); gulp.task("default", function() { gulp.src("./*.js") .on("data", function(file) { console.log("data callback"); console.log(file.inspect()); /* It outputs: * data callback * > * data callback * > */ }) .pipe(gulp.dest("dist/")); });
Содержимое может быть представлено в двух форматах: в виде уже прочитанного буфера, или же в виде родного нодовского потока. Каждая ступень галповского пайпа берет на вход такие вот файлы, делает некую трансформацию и передает на выход следующей цепочке. Последняя цепочка обычно просто сохраняет их на диск.

Pipe(gulp.dest("dist/"));
Осознание факта того, что потоки в gulp другие ведет к просветлению и пониманию, поскольку это объясняет большинство проблем и ошибок.

Рассмотрим реальный пример. Вы хотите использовать browserify для склейки ваших JS файлов. Вы идете, и находите плагин gulp-browserify . Но видите приписку, которая говорит, что плагин deprecated, т.е. Устарел.

Как хорошо воспитанный программист вы отметаете этот вариант, и идете искать, а какое же решение не устарело. Находите официальные рецепты от gulp, и видите , что browserify работает с галпом напрямую. Ну как напрямую, через прослойку , которая как раз и переводит родной нодовский поток в виниловский поток, который понимает gulp. Без него ничего бы не заработало, поскольку это разные потоки.

Если вы хотите написать свою трансформацию, то можете использовать данный шаблон .
Как видим, здесь все просто: на каждый файл будет вызываться наш обработчик, который и выполнит модификации. Мы можем делать все что захотим: изменить содержимое файла, переименовать файл, удалить файл или добавить еще пару новых файлов в поток.

Как мы помним, содержимое файла в виниловском потоке может быть представлено в виде буфера или в виде потока данных. Однако не обязательно поддерживать и то другое. Всегда можно использовать пакет

Всем привет, друзья! Сегодня мы подробно рассмотрим, что такое Gulp и как с его помощью можно автоматизировать работу Front-end разработчика. В результате урока мы соберем серьезное и внушительное рабочее Front-end окружение для веб-разработки с использованием Gulp.

Видео урок:

Класснуть

Запинить

  • Урок по обновлению Gulp до 4 версии: Ознакомиться с уроком Gulp 4
https://github.com/agragregra/gulp-lesson

Gulp - это инструмент, который помогает автоматизировать рутинные задачи веб-разработки. Gulp предназначен для решения таких задач, как:

  • Создание веб-сервера и автоматическая перезагрузка страницы в браузере при сохранении кода, слежение за изменениями в файлах проекта;
  • Использование различных JavaScript, CSS и HTML препроцессоров (CoffeeScript, Less, Sass, Stylus, Jade и т.д.);
  • Минификация CSS и JS кода, а также, оптимизация и конкатенация отдельных файлов проекта в один;
  • Автоматическое создание вендорных префиксов (приставок к названию CSS свойства, которые добавляют производители браузеров для нестандартных свойств) для CSS.
  • Управление файлами и папками в рамках проекта - создание, удаление, переименование;
  • Запуск и контроль выполнения внешних команд операционной системы;
  • Работа с изображениями - сжатие, создание спрайтов, ресайз (png, jpg, svg и др.);
  • Деплой (отправка на внешний сервер) проекта по FTP, SFTP, Git и т.д.
  • Подключение и использование в проекте безгранично большого количества Node.js и Gulp утилит, программ и плагинов.
  • Создание различных карт проекта и автоматизация другого ручного труда.

Можно с уверенностью сказать, что Gulp и множество утилит, написанных для него, подходят для решения практически любой задачи при разработке проекта любой сложности - от небольшого сайта до крупного проекта.

Любой проект, использующий Gulp имеет в корне файл gulpfile.js , который содержит набор инструкций по управлению проектом. Сразу хочется сказать, что написание инструкций для Gulp не является программированием, хотя пишутся на языке JavaScript. Не стоит пугаться больших gulpfile.js, в основном все инструкции однотипные и имеют общие черты. К тому времени, как вы прочтете данное руководство, у вас не должно остаться вопросов по Gulp, так как система сборки элементарная. Но если у вас останутся вопросы - обязательно пишите в комментариях.

Установка Gulp

Внимание! Если вы пользователь последней версии Windows, рекомендую использовать терминал Bash для веб-разработки. Скачивать инсталлятор с сайта Nodejs.org в этом случае не нужно. Воспользуйтесь этим руководством: .
Если у вас возникли проблемы при прохождении урока с использованием Gulp 4, рекомендую откатиться на 3 версию, пройти полностью урок и только после этого обновить package.json до 4 версии. Для лучшего понимания. Откатить версию можно в файле package.json. Вместо "gulp": "^4.x.x", напишите версию "^3.9.1", удалите папку "node_modules" и установите пакеты заново "npm i ".

Для работы с Gulp у вас должен быть установлен Node.js. Установка Node.js для различных платформ довольно простая - скачиваете инсталлер Node для своей операционной системы и устанавливаете. Я рекомендую устанавливать последнюю версию Stable. Для пользователей Linux и последней версии Windows я подготовил отдельное руководство по установке: Использование подсистемы Linux для веб-разработки в Windows 10 .

После того, как Node установлен, можно приступать к установке Gulp. Откройте терминал (правая кнопка мыши в папке с зажатым Shift > Откройте здесь оболочку Linux) и выполните следующую команду:

Npm i gulp -g

Для пользователей Mac и Linux и Ubuntu bash в Windows, глобальную установку с ключом -g необходимо выполнять с правами суперпользователя, sudo , например:
sudo npm i gulp -g .

Из данной команды мы видим, что запускается менеджер пакетов npm (Node Package Manager), который командой install устанавливает Gulp в систему. Ключ -g говорит о том, что пакет установится в систему глобально, то-есть в систему, а не в папку проекта. Без ключа -g пакет устанавливаются в ту папку, в которой выполняются текущие команды, поэтому будьте внимательны.

Создание проекта Gulp

Давайте создадим папку проекта для примера, с которой будем работать, пусть это будет, например, папка myproject .

Очень важно! Не создавайте русскоязычные папки проектов и следите за тем, чтобы путь до папки проекта не содержал кириллических символов, то-есть не был написан на русском языке. В противном случае, у вас могут возникнуть проблемы при работе различных утилит Gulp. Папка вашего пользователя также не должна быть русскоязычной. Всё только латинскими буквами.

Теперь откроем терминал в папке проекта. Для пользователей Windows достаточно зажать Shift и открыть контекстное меню. В нем появится пункт "Откройте здесь оболочку Linux". Оболочка Linux должна быть предварительно установлена, см урок: Использование подсистемы Linux для веб-разработки в Windows .

Npm init

Следуя инструкциям, заполним метаинформацию о нашем проекте:

В результате такой несложной первоначальной настройки нашего нового Gulp проекта в папке myproject нарисуется новый файл package.json .


Файл package.json является файлом манифеста нашего проекта, который описывает помимо той информации, что мы внесли в терминале, еще и информацию об используемых пакетах в нашем проекте.

Например, если мы установим в проект Gulp с ключом --save-dev , то пакет и используемая версия автоматически добавится в наш package.json. Такой учет позволит быстро разворачивать новый проект с использованием уже имеющегося package.json и устанавливать необходимые модули с зависимостями, которые прописаны в package.json в новых проектах.

Давайте установим в наш проект Gulp:

Npm i gulp --save-dev

Что мы видим из данной строки: npm устанавливает пакет gulp в текущую папку myproject (потому, что нет ключа -g, устанавливающий пакет глобально в систему) и сохраняет название пакета с версией в файл package.json:


Кроме того, у нас появляется папка node_modules , которая теперь содержит установленный пакет gulp и необходимые зависимости. В данную папку автоматически будут сваливаться все модули и зависимости, которые мы будем устанавливать в проект. Папок с зависимостями может быть очень много, не смотря на то, что мы установили не так уж и много пакетов. Это связано с тем, что в дополнение к основным пакетам устанавливаются программы, необходимые для корректной работы основного пакета. Ни чего чистить и удалять из папки node_modules не нужно. Кроме того, у вас может появиться дополнительный файл package-lock.json . В этом нет ничего страшного, это служебный файл, на который можно просто не обращать внимания.

Структура каталогов в проектах

Работая с различными плагинами, программами и скриптами, будь то jQuery плагин, модуль для CMS, веб-проект или какое-то другое ПО, вы наверняка замечали, что у всех проектов есть схожая структура каталогов, например, большинство проектов имеет папку dist и app . Давайте создадим первоначальную структуру нашего учебного проекта. В результате мы должны создать следующую структуру в нашем проекте myproject (все файлы, которых не было, пока создаем пустыми):

  • myproject/
    • app/
      • css/
      • fonts/
      • img/
      • js/
      • sass/
      • index.html
    • dist/
    • node_modules/
    • gulpfile.js
    • package.json
Данная структура встречается довольно часто, практически во всех проектах, но это не аксиома и некоторые проекты могут иметь вообще другую структуру. Для данной статьи мы будем использовать именно такую структуру проекта.

Здесь мы видим папку app/ , в которой будут размещены все исходные материалы проекта - оригинальные CSS, Sass, js файлы библиотек, оригинальные изображения. В общем - это папка исходников нашего проекта.

Папка dist/ будет содержать уже готовый продукт, оптимизированный, сжатый, причесанный. Это папка продакшена.

gulpfile.js

Теперь давайте откроем в редакторе кода gulpfile.js и напишем в него:

Var gulp = require("gulp");

Данной строчкой мы подключаем Gulp к нашему проекту, посредством функции require . Данная функция подключает пакеты из папки node_modules в наш проект, присваивая их переменной. В данном случае, мы создаем переменную gulp .

Gulp.task("mytask", function() { console.log("Привет, я таск!"); });

mytask - это название команды, которую вы будете вызывать в нужном вам месте gulpfile.js. Кроме того, можно в командной строке выполнить таск напрямую, написав:

Gulp mytask

gulpfile.js :


Результат выполнения команды gulp mytask :


Если вы используете Gulp 4 и у вас появляется ошибка о невозможности завершения таска, можно добавить async перед function() и выполнять код асинхронно: var gulp = require("gulp"); gulp.task("mytask", async function() { console.log("Привет, я таск!"); });

Это, конечно очень простой базовый пример создания таска. Как правило, таски несколько сложнее и включают некоторые дополнительные команды:

Gulp.task("mytask", function () { return gulp.src("source-files") // Выборка исходных файлов для обработки плагином.pipe(plugin()) // Вызов Gulp плагина для обработки файла.pipe(gulp.dest("folder")) // Вывод результирующего файла в папку назначения (dest - пункт назначения) })

  • gulp.src - выборка исходных файлов проекта для обработки плагином;
  • .pipe(plugin()) - вызов Gulp плагина для обработки файла;
  • .pipe(gulp.dest("folder")) - вывод результирующего файла в папку назначения (dest - пункт назначения).

Это база Gulp, теперь можно создавать инструкции. Для начала давайте создадим обработчик, который будет компилировать Sass файлы в CSS (CSS препроцессинг).

Gulp Sass

Давайте установим пакет gulp-sass в наш проект с сохранением версии и названия в package.json.

Обратите внимание, что любые Gulp пакеты, для любых задач, легко гуглятся и имеют вполне исчерпывающие инструкции по подключению на своих хоумпейджах и в документации.
npm i gulp-sass --save-dev

Var gulp = require("gulp"), sass = require("gulp-sass"); //Подключаем Sass пакет

Давайте создадим в папке app/sass файл main.sass , зададим в нем фон body - черный и напишем для него обработчик в gulpfile.js


gulpfile.js :

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"); //Подключаем Sass пакет gulp.task("sass", function(){ // Создаем таск "sass" return gulp.src("app/sass/main.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css });

После этого, логичным будет выполнить в терминале наш новый таск sass :

Gulp sass

В результате выполения данной команды в папке app/css появится файл main.css .


От таки чудеса, друзя. Как видим, все просто:-)

Выборка файлов для gulp.src

В принципе, мы рассмотрели все, что необходимо знать о Gulp, теперь будем углубляться в каждую деталь того, что было изложено выше.

Выборка файлов в примере выше довольно простая, мы брали файл напрямую: gulp.src("app/sass/main.sass") . Но файлы также можно выбирать по шаблону. Шаблон выборки файлов называется glob - https://en.wikipedia.org/wiki/Glob_(programming) . Давайте познакомимся ближе со всеми возможностями выборки файлов для обработки.

Самые распространенные шаблоны выборки

  • *.sass - выбирает все файлы, имеющие определенное расширение (в данном случае, .sass) в корневой папке проекта.
  • **/*.js - выбирает все файлы с расширением .js во всех папках проекта.
  • !header.sass - исключает файл из общей выборки
  • *.+(scss|sass) - задает комплексный шаблон для нескольких типов файлов, разделенных вертикальной чертой. В данном примере в выборкупопадут любые sass и scss файлы в корне проекта.

Давайте внесем некоторые изменения в таск sass и сделаем его более универсальным:

Gulp.task("sass", function(){ return gulp.src("app/sass/**/*.sass") // Берем все sass файлы из папки sass и дочерних, если таковые будут.pipe(sass()) .pipe(gulp.dest("app/css")) });

Дело в том, что брать напрямую один отдельный файл не всегда удобно, так как в папке sass могут появиться и другие файлы с расширением sass, которые могут использоваться в проекте.

Обратите внимание, что файлы sass, которые предназначены для импорта в другие файлы, как части одного общего, начинаются с нижнего подчеркивания _part-1.sass . Такие файлы не учавствуют в компиляции, как отдельные файлы, а добавляются через @import в основные файлы.

Наблюдение за изменениями в файлах (Gulp Watch)

Gulp поддерживает метод watch для проверки сохраняемых файлов и имеет следующий синтаксис:

Gulp.watch("watch-files", ["task1", "task2"]);

Если мы, например, хотим наблюдать за всеми изменениями в файлах sass нашего проекта, то можем использовать следующую конструкцию:

Gulp.watch("app/sass/**/*.sass", ["sass"]);

Что мы видим: Gulp наблюдает за всеми sass файлами и при сохранении выполняет таск sass, который автоматически компилирует их в css файлы.

Также, мы можем создать отдельный таск для наблюдения за всеми необходимыми файлами

Gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", ["sass"]); // Наблюдение за sass файлами // Наблюдение за другими типами файлов });

Для Gulp 4 код будет выглядеть так: gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); });

Если мы запустим в консоли gulp watch , то Gulp будет автоматически следить за всеми измененями в файлах sass при сохранении и компилировать их в css.

Было бы неплохо в дополнение к этой красоте сделать автоматическую перезагрузку страницы при изменениях в файлах. Для этой задачи нам подойдет Browser Sync .

Автоматическое обновление страниц с использованием Bbrowser Sync

Browser Sync - это отличное решение для LiveReload страниц при сохранении файлов. При чем релоад происходит не только в одном браузере, но и во всех браузерах сети, будь это мобильные устройства или другие компьютеры в одной Wi-Fi сети.

Мы уже умеем устанавливать дополнения для Gulp, поэтому давайте установим Browser Sync в наш проект:

Npm i browser-sync --save-dev

И, конечно-же, подключим в файле gulpfile.js, как мы это делали ранее с пакетом gulp-sass.

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"); // Подключаем Browser Sync

Создаем таск для Browser Sync:

Gulp.task("browser-sync", function() { // Создаем таск browser-sync browserSync({ // Выполняем browser Sync server: { // Определяем параметры сервера baseDir: "app" // Директория для сервера - app }, notify: false // Отключаем уведомления }); });

Отлично! Наш сервер для работы и автоматического релоада готов. Теперь давайте последим за изменениями в Sass. Если файл Sass обновляется, автоматически инжектим в HTML измененный CSS файл:

Gulp.task("sass", function(){ // Создаем таск Sass return gulp.src("app/sass/**/*.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css .pipe(browserSync.reload({stream: true})) // Обновляем CSS на странице при изменении });

Все, что нам осталось сделать - это запустить таск browser-sync перед тем, как запустится gulp watch . Немного модифицируем таск watch , добавив выполнение browser-sync и sass до запуска watch :

Gulp.task("watch", ["sass", "browser-sync"], function() { gulp.watch("app/sass/**/*.sass", ["sass"]); // Наблюдение за sass файлами // Наблюдение за другими типами файлов });

Обратите внимание, что мы выполняем таски ["sass", "browser-sync"] до запуска watch , так как их выполнение необходимо нам для корректного отображения изменений на момент запуска сервера.
Для Gulp 4 логичнее было бы написать так и выполнять всю конструкцию в дефолтном таске: gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); }); gulp.task("default", gulp.parallel("sass", "browser-sync", "watch"));

Расположим таск watch после всех других тасков и в результате получим такой gulpfile.js для Gulp 3:

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"); // Подключаем Browser Sync gulp.task("sass", function(){ // Создаем таск Sass return gulp.src("app/sass/**/*.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css .pipe(browserSync.reload({stream: true})) // Обновляем CSS на странице при изменении }); gulp.task("browser-sync", function() { // Создаем таск browser-sync browserSync({ // Выполняем browserSync server: { // Определяем параметры сервера baseDir: "app" // Директория для сервера - app }, notify: false // Отключаем уведомления }); }); gulp.task("watch", ["sass", "browser-sync"], function() { gulp.watch("app/sass/**/*.sass", ["sass"]); // Наблюдение за sass файлами // Наблюдение за другими типами файлов });

Такой код получится для Gulp 4:

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"); // Подключаем Browser Sync gulp.task("sass", function(){ // Создаем таск Sass return gulp.src("app/sass/**/*.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css .pipe(browserSync.reload({stream: true})) // Обновляем CSS на странице при изменении }); gulp.task("browser-sync", function() { // Создаем таск browser-sync browserSync({ // Выполняем browserSync server: { // Определяем параметры сервера baseDir: "app" // Директория для сервера - app }, notify: false // Отключаем уведомления }); }); gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); // Наблюдение за sass файлами }); gulp.task("default", gulp.parallel("sass", "browser-sync", "watch"));

Для того, чтобы следить за изменениями в браузере, сделаем соответствующую разметку в файле index.html директории app с подключением файла стилей main.css :

Document

Выполним в терминале команду "gulp". Результат завораживает:


Давайте разберемся, что у нас происходит в консоли (картина может разниться, в зависимости от версии ПО):


После того, как мы нарадуемся результату, встает весьма ожидаемый вопрос - а как, собтвенно, обновлять страницу при сохранении HTML и JS?

И эта задача нам по плечу. Создайте в папке app/js файл common.js . Это основной пользовательский JS файл в нашем проекте. Модифицируем код:

Код для Gulp 3:

Gulp.task("watch", ["sass", "browser-sync"], function() { gulp.watch("app/sass/**/*.sass", ["sass"]); // Наблюдение за sass файлами в папке sass gulp.watch("app/*.html", browserSync.reload); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], browserSync.reload); // Наблюдение за главным JS файлом и за библиотеками });

Код для Gulp 4 (здесь лучше добавить дополнительный таск для обработки HTML и JS):

Gulp.task("scripts", function() { return gulp.src(["app/js/common.js", "app/libs/**/*.js"]) .pipe(browserSync.reload({ stream: true })) }); gulp.task("code", function() { return gulp.src("app/*.html") .pipe(browserSync.reload({ stream: true })) }); gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); // Наблюдение за sass файлами gulp.watch("app/*.html", gulp.parallel("code")); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], gulp.parallel("scripts")); // Наблюдение за главным JS файлом и за библиотеками }); gulp.task("default", gulp.parallel("sass", "browser-sync", "watch"));

Здесь мы используем функцию browserSync.reload, которую нам любезно предоставил пакет Browser Sync. Обратите внимание на выборку файлов для слежения.

В принципе, мы уже имеем довольно продвинутое рабочее окружение. Но двигаемся дальше, это не все, на что способен Gulp.

Оптимизация JavaScript

Давайте рассмотрим, как можно оптимизировать JS файлы проекта. Чаще всего, в оптимизации нуждаются библиотеки и сторонние jQuery и JavaScript плагины. Давайте создадим в папке app паку libs , которая будет содержать необходимые проекту библиотеки. Все библиотеки будем размещать в отдельных папках. Для установки новых библиотек я советую использовать Bower .

Установим Bower:

Npm i -g bower

Обратите внимание, что для работы Bower необходим установленный Git . Если в ОС Windows вы используте оболочку Ubuntu bash, то установку Git выполнять не нужно.

Теперь в папке проекта создадим файл .bowerrc , в который напишем:

{ "directory" : "app/libs/" }

Если вы пользователь ОС Windows, у вас не получится просто взять и создать файл, начинающийся с точки. В этом случае можно просто поставить точку в конце файла и нажать Enter: .bowerrc.

Данной настройкой мы указываем путь по умолчанию для установки плагинов с помощью Bower.

Установим jQuery и Magnific Popup, для примера:

Bower i jquery magnific-popup

Обратите внимание, что все (ну, или почти все) плагины имеют папку dist, об этом мы говорили ранее. В этой папке располагаются готовые файлы продакшена, которые мы и будем использовать в нашем проекте.

Давайте создадим таск scripts , который будет собирать все JS файлы библиотек в один и минифицировать файл. Для этого установим 2 пакета: gulp-concat и gulp-uglifyjs .

Npm i --save-dev gulp-concat gulp-uglifyjs

Подключим новые библиотеки в gulpfile.js:

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"); // Подключаем gulp-uglifyjs (для сжатия JS)

Создаем задачу для сборки и сжатия всех библиотек (перед watch):

Gulp.task("scripts", function() { return gulp.src([ // Берем все необходимые библиотеки "app/libs/jquery/dist/jquery.min.js", // Берем jQuery "app/libs/magnific-popup/dist/jquery.magnific-popup.min.js" // Берем Magnific Popup ]) .pipe(concat("libs.min.js")) // Собираем их в кучу в новом файле libs.min.js .pipe(uglify()) // Сжимаем JS файл.pipe(gulp.dest("app/js")); // Выгружаем в папку app/js });

Давайте проверим, как работает наш новый таск scripts , выполнив в терминале:


Выполнение таска scripts можно запустить перед выполнением watch. Gulp 3:


Для Gulp 4 код будет выглядеть следующим образом - добавим в параллельное выполнение таска scripts (некоторую структуру уже задали ранее): gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); // Наблюдение за sass файлами gulp.watch("app/*.html", gulp.parallel("code")); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], gulp.parallel("scripts")); // Наблюдение за главным JS файлом и за библиотеками }); gulp.task("default", gulp.parallel("sass", "scripts", "browser-sync", "watch"));

Далее можно подключить к проекту все необходимые CSS файлы библиотек. В нашем случае, только одна библиотека нуждается в подключении - это Magnific Popup. Сделаем это через @import в Sass фале sass/libs.sass :

@import "app/libs/magnific-popup/dist/magnific-popup.css" // Импортируем библиотеку Magnific Popup

Внимание! В новых версиях gulp-sass для импорта CSS файлов в Sass необходимо указывать расширение.css и импортировать CSS файлы в SASS файлы с нижним подчёркиванием в начале названия. Например, для того, чтобы импортировать файл library-name.css, необходимо создать вспомогатальный SASS файл, например, _libs.sass, импортировать в него нужный CSS - @import "app/libs/library-name.css" и добавить вспомогательный _libs.sass в главный main.sass без указания нижнего подчёркивания и расширения, например, так: @import "libs"

На выходе, в папке app/css мы получаем дополнительно к main.css файл libs.css, который содержит стили всех библиотек. Файл main.css нет особого смысла минифицировать, так как он содержит кастомные (пользовательские) стили. А вот файл libs.css мы с удовольствием минифицируем.

Внимание! Если в файле libs.css не появляется кода библиотек, а вы по-прежнему видите в нём конструкции @import, создайте отдельный файл _libs.sass для библиотек, который начинался бы с нижнего подчёркивания . Затем импортируйте этот файл в главный, тем самым объеденив и библиотеки и пользовательские стили в один файл.

Для минификации CSS установим пакеты gulp-cssnano и gulp-rename :

Npm i gulp-cssnano gulp-rename --save-dev

И подключим их в нашем gulpfile.js:

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"); // Подключаем библиотеку для переименования файлов

И создадим соответствующий таск css-libs . Сразу добавим данный таск в watch для того, чтобы библиотеки собирались в процессе запуска проекта. Таск sass лучше вызвать до запуска css-libs, чтобы нам было что минифицировать:

Gulp.task("css-libs", ["sass"], function() { return gulp.src("app/sass/libs.sass") // Выбираем файл для минификации.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(cssnano()) // Сжимаем.pipe(rename({suffix: ".min"})) // Добавляем суффикс.min .pipe(gulp.dest("app/css")); // Выгружаем в папку app/css }); gulp.task("watch", ["browser-sync", "css-libs", "scripts"], function() { gulp.watch("app/sass/**/*.sass", ["sass"]); // Наблюдение за sass файлами в папке sass gulp.watch("app/*.html", browserSync.reload); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], browserSync.reload); // Наблюдение за главным JS файлом и за библиотеками });

Код для Gulp 4:

Gulp.task("css-libs", function() { return gulp.src("app/sass/libs.sass") // Выбираем файл для минификации.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(cssnano()) // Сжимаем.pipe(rename({suffix: ".min"})) // Добавляем суффикс.min .pipe(gulp.dest("app/css")); // Выгружаем в папку app/css }); gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); // Наблюдение за sass файлами gulp.watch("app/*.html", gulp.parallel("code")); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], gulp.parallel("scripts")); // Наблюдение за главным JS файлом и за библиотеками }); gulp.task("default", gulp.parallel("css-libs", "sass", "scripts", "browser-sync", "watch"));

Подготовка к продакшену

Результирующий код для Gulp 4 будет представлен в конце статьи.

Для продакшена (сборки в папку dist) мы создадим отдельный таск build в конце gulpfile.js. В данной инструкции мы осуществим сборку Sass, JS и выгрузку того, что у нас готово в папку dist.

Gulp.task("build", ["sass", "scripts"], function() { var buildCss = gulp.src([ // Переносим CSS стили в продакшен "app/css/main.css", "app/css/libs.min.css" ]) .pipe(gulp.dest("dist/css")) var buildFonts = gulp.src("app/fonts/**/*") // Переносим шрифты в продакшен.pipe(gulp.dest("dist/fonts")) var buildJs = gulp.src("app/js/**/*") // Переносим скрипты в продакшен.pipe(gulp.dest("dist/js")) var buildHtml = gulp.src("app/*.html") // Переносим HTML в продакшен.pipe(gulp.dest("dist")); });

Здесь, присваивая переменным какие-либо действия, мы их выполняем. Таким образом можно выполнять мультизадачные таски. Можно и не присваивать, но мы сделаем так, ибо красивше.

Все прекрасно, но всегда есть одно "Но". Перед тем, как собирать проект нам желательно бы очистить папку dist, чтобы не оставалось лишних потрохов от предыдущих итераций с нашим проектом.

Установим и подключим пакет del:

Npm i del --save-dev var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"), // Подключаем библиотеку для переименования файлов del = require("del"); // Подключаем библиотеку для удаления файлов и папок

Создаем таск очистки clean и добавляем его выполнение перед выполнение build:

Gulp.task("clean", function() { return del.sync("dist"); // Удаляем папку dist перед сборкой }); gulp.task("build", ["clean", "sass", "scripts"], function() { var buildCss = gulp.src([ // Переносим библиотеки в продакшен "app/css/main.css", "app/css/libs.min.css" ]) .pipe(gulp.dest("dist/css")) var buildFonts = gulp.src("app/fonts/**/*") // Переносим шрифты в продакшен.pipe(gulp.dest("dist/fonts")) var buildJs = gulp.src("app/js/**/*") // Переносим скрипты в продакшен.pipe(gulp.dest("dist/js")) var buildHtml = gulp.src("app/*.html") // Переносим HTML в продакшен.pipe(gulp.dest("dist")); });

Для Gulp 4 попробуйте составить таски самостоятельно, как мы это делали в предыдущих прмерах.

Оптимизация изображений

Как вы могли заметить, в нашем проекте на продакшене не хватает изображений. Давайте исправим это недоразумение и добавим обработку изображений в наш проект. Данный раздел выполнен с использованием Gulp 3. Код для Gulp 4 можно адаптировать самостоятельно, как мы это делали ранее.

В папке app/img есть 3 изображения, которые нам необходимо перенести в папку продакшена, оптимизируя.


Для оптимизации изображений установим 2 пакета (gulp-imagemin , imagemin-pngquant ) и подключим их:

Npm i gulp-imagemin imagemin-pngquant --save-dev var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"), // Подключаем библиотеку для переименования файлов del = require("del"), // Подключаем библиотеку для удаления файлов и папок imagemin = require("gulp-imagemin"), // Подключаем библиотеку для работы с изображениями pngquant = require("imagemin-pngquant"); // Подключаем библиотеку для работы с png

Gulp.task("img", function() { return gulp.src("app/img/**/*") // Берем все изображения из app .pipe(imagemin({ // Сжимаем их с наилучшими настройками interlaced: true, progressive: true, svgoPlugins: [{removeViewBox: false}], use: })) .pipe(gulp.dest("dist/img")); // Выгружаем на продакшен }); gulp.task("build", ["clean", "img", "sass", "scripts"], function() { var buildCss = gulp.src([ // Переносим библиотеки в продакшен "app/css/main.css", "app/css/libs.min.css" ]) .pipe(gulp.dest("dist/css")) var buildFonts = gulp.src("app/fonts/**/*") // Переносим шрифты в продакшен.pipe(gulp.dest("dist/fonts")) var buildJs = gulp.src("app/js/**/*") // Переносим скрипты в продакшен.pipe(gulp.dest("dist/js")) var buildHtml = gulp.src("app/*.html") // Переносим HTML в продакшен.pipe(gulp.dest("dist")); });

Все прекрасно. До тех пор, пока количество изображений в проекте не превышает 3 шт. Большое количество картинок будет обрабатываться значительно дольше, поэтому к обработке изображений было бы неплохо добавить кеш, чтобы картинки кешировались, экономя наше время.

Установи м подключим gulp-cache :

Npm i gulp-cache --save-dev var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"), // Подключаем библиотеку для переименования файлов del = require("del"), // Подключаем библиотеку для удаления файлов и папок imagemin = require("gulp-imagemin"), // Подключаем библиотеку для работы с изображениями pngquant = require("imagemin-pngquant"), // Подключаем библиотеку для работы с png cache = require("gulp-cache"); // Подключаем библиотеку кеширования

Модифицируем таск img :

Gulp.task("img", function() { return gulp.src("app/img/**/*") // Берем все изображения из app .pipe(cache(imagemin({ // Сжимаем их с наилучшими настройками с учетом кеширования interlaced: true, progressive: true, svgoPlugins: [{removeViewBox: false}], use: }))) .pipe(gulp.dest("dist/img")); // Выгружаем на продакшен });

Автоматическое создание префиксов CSS с помощью Gulp

Вендорные префиксы необходимы для обеспечения максимальной совместимости со всеми современными браузерами. Было бы логично сделать автоматическое добавление префиксов, чтобы написав в CSS или Sass:

Display: flex

Мы получили на выходе:

Display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: -o-flex; display: flex;

Установим пакет gulp-autoprefixer и подключим его в gulpfile.js:

Npm i --save-dev gulp-autoprefixer var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"), // Подключаем библиотеку для переименования файлов del = require("del"), // Подключаем библиотеку для удаления файлов и папок imagemin = require("gulp-imagemin"), // Подключаем библиотеку для работы с изображениями pngquant = require("imagemin-pngquant"), // Подключаем библиотеку для работы с png cache = require("gulp-cache"), // Подключаем библиотеку кеширования autoprefixer = require("gulp-autoprefixer");// Подключаем библиотеку для автоматического добавления префиксов

И модифицируем наш таск sass :

Gulp.task("sass", function(){ // Создаем таск Sass return gulp.src("app/sass/**/*.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(autoprefixer(["last 15 versions", "> 1%", "ie 8", "ie 7"], { cascade: true })) // Создаем префиксы.pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css .pipe(browserSync.reload({stream: true})) // Обновляем CSS на странице при изменении });

Дефолтный таск Gulp

Внимание! Дефолтный таск для Gulp 4 отличается от приведённого в этой главе. Полный код для Gulp 4 можно будет посмотреть в конце статьи.

Итак, мы имеем 2 главных таска - gulp watch - для работы над проектом в режиме "онлайн" и gulp build - для сборки проекта на продакшен без лишних файлов, папок и со сжатыми картинками. Так как чаще всего нам нужен будет таск watch , можно повесить его на дефолтный таск, чтобы не писать в консоли постоянно gulp watch, а писать просто gulp .

Gulp.task("default", ["watch"]);

Также, необходимо создать автономный таск для очистки кеша Gulp, чтобы его можно было вызывать простой командой gulp clear :

Gulp.task("clear", function () { return cache.clearAll(); })

Если у вас возникнут проблемы с изображениями или другими кешируемыми файлами, просто почистите кеш.

В результате, у нас должен получиться такой gulpfile.js . Gulp 3:

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"), // Подключаем библиотеку для переименования файлов del = require("del"), // Подключаем библиотеку для удаления файлов и папок imagemin = require("gulp-imagemin"), // Подключаем библиотеку для работы с изображениями pngquant = require("imagemin-pngquant"), // Подключаем библиотеку для работы с png cache = require("gulp-cache"), // Подключаем библиотеку кеширования autoprefixer = require("gulp-autoprefixer");// Подключаем библиотеку для автоматического добавления префиксов gulp.task("sass", function(){ // Создаем таск Sass return gulp.src("app/sass/**/*.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(autoprefixer(["last 15 versions", "> 1%", "ie 8", "ie 7"], { cascade: true })) // Создаем префиксы.pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css .pipe(browserSync.reload({stream: true})) // Обновляем CSS на странице при изменении }); gulp.task("browser-sync", function() { // Создаем таск browser-sync browserSync({ // Выполняем browserSync server: { // Определяем параметры сервера baseDir: "app" // Директория для сервера - app }, notify: false // Отключаем уведомления }); }); gulp.task("scripts", function() { return gulp.src([ // Берем все необходимые библиотеки "app/libs/jquery/dist/jquery.min.js", // Берем jQuery "app/libs/magnific-popup/dist/jquery.magnific-popup.min.js" // Берем Magnific Popup ]) .pipe(concat("libs.min.js")) // Собираем их в кучу в новом файле libs.min.js .pipe(uglify()) // Сжимаем JS файл.pipe(gulp.dest("app/js")); // Выгружаем в папку app/js }); gulp.task("css-libs", ["sass"], function() { return gulp.src("app/css/libs.sass") // Выбираем файл для минификации.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(cssnano()) // Сжимаем.pipe(rename({suffix: ".min"})) // Добавляем суффикс.min .pipe(gulp.dest("app/css")); // Выгружаем в папку app/css }); gulp.task("clean", function() { return del.sync("dist"); // Удаляем папку dist перед сборкой }); gulp.task("img", function() { return gulp.src("app/img/**/*") // Берем все изображения из app .pipe(cache(imagemin({ // С кешированием // .pipe(imagemin({ // Сжимаем изображения без кеширования interlaced: true, progressive: true, svgoPlugins: [{removeViewBox: false}], use: }))/**/) .pipe(gulp.dest("dist/img")); // Выгружаем на продакшен }); gulp.task("build", ["clean", "img", "sass", "scripts"], function() { var buildCss = gulp.src([ // Переносим библиотеки в продакшен "app/css/main.css", "app/css/libs.min.css" ]) .pipe(gulp.dest("dist/css")) var buildFonts = gulp.src("app/fonts/**/*") // Переносим шрифты в продакшен.pipe(gulp.dest("dist/fonts")) var buildJs = gulp.src("app/js/**/*") // Переносим скрипты в продакшен.pipe(gulp.dest("dist/js")) var buildHtml = gulp.src("app/*.html") // Переносим HTML в продакшен.pipe(gulp.dest("dist")); }); gulp.task("clear", function (callback) { return cache.clearAll(); }); gulp.task("watch", ["browser-sync", "css-libs", "scripts"], function() { gulp.watch("app/sass/**/*.sass", ["sass"]); // Наблюдение за sass файлами в папке sass gulp.watch("app/*.html", browserSync.reload); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], browserSync.reload); // Наблюдение за JS файлами в папке js }); gulp.task("default", ["watch"]);

Результирующий код для Gulp 4:

Var gulp = require("gulp"), // Подключаем Gulp sass = require("gulp-sass"), //Подключаем Sass пакет, browserSync = require("browser-sync"), // Подключаем Browser Sync concat = require("gulp-concat"), // Подключаем gulp-concat (для конкатенации файлов) uglify = require("gulp-uglifyjs"), // Подключаем gulp-uglifyjs (для сжатия JS) cssnano = require("gulp-cssnano"), // Подключаем пакет для минификации CSS rename = require("gulp-rename"), // Подключаем библиотеку для переименования файлов del = require("del"), // Подключаем библиотеку для удаления файлов и папок imagemin = require("gulp-imagemin"), // Подключаем библиотеку для работы с изображениями pngquant = require("imagemin-pngquant"), // Подключаем библиотеку для работы с png cache = require("gulp-cache"), // Подключаем библиотеку кеширования autoprefixer = require("gulp-autoprefixer");// Подключаем библиотеку для автоматического добавления префиксов gulp.task("sass", function() { // Создаем таск Sass return gulp.src("app/sass/**/*.sass") // Берем источник.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(autoprefixer(["last 15 versions", "> 1%", "ie 8", "ie 7"], { cascade: true })) // Создаем префиксы.pipe(gulp.dest("app/css")) // Выгружаем результата в папку app/css .pipe(browserSync.reload({stream: true})) // Обновляем CSS на странице при изменении }); gulp.task("browser-sync", function() { // Создаем таск browser-sync browserSync({ // Выполняем browserSync server: { // Определяем параметры сервера baseDir: "app" // Директория для сервера - app }, notify: false // Отключаем уведомления }); }); gulp.task("scripts", function() { return gulp.src([ // Берем все необходимые библиотеки "app/libs/jquery/dist/jquery.min.js", // Берем jQuery "app/libs/magnific-popup/dist/jquery.magnific-popup.min.js" // Берем Magnific Popup ]) .pipe(concat("libs.min.js")) // Собираем их в кучу в новом файле libs.min.js .pipe(uglify()) // Сжимаем JS файл.pipe(gulp.dest("app/js")); // Выгружаем в папку app/js }); gulp.task("code", function() { return gulp.src("app/*.html") .pipe(browserSync.reload({ stream: true })) }); gulp.task("css-libs", function() { return gulp.src("app/css/libs.sass") // Выбираем файл для минификации.pipe(sass()) // Преобразуем Sass в CSS посредством gulp-sass .pipe(cssnano()) // Сжимаем.pipe(rename({suffix: ".min"})) // Добавляем суффикс.min .pipe(gulp.dest("app/css")); // Выгружаем в папку app/css }); gulp.task("clean", async function() { return del.sync("dist"); // Удаляем папку dist перед сборкой }); gulp.task("img", function() { return gulp.src("app/img/**/*") // Берем все изображения из app .pipe(cache(imagemin({ // С кешированием // .pipe(imagemin({ // Сжимаем изображения без кеширования interlaced: true, progressive: true, svgoPlugins: [{removeViewBox: false}], use: }))/**/) .pipe(gulp.dest("dist/img")); // Выгружаем на продакшен }); gulp.task("prebuild", async function() { var buildCss = gulp.src([ // Переносим библиотеки в продакшен "app/css/main.css", "app/css/libs.min.css" ]) .pipe(gulp.dest("dist/css")) var buildFonts = gulp.src("app/fonts/**/*") // Переносим шрифты в продакшен.pipe(gulp.dest("dist/fonts")) var buildJs = gulp.src("app/js/**/*") // Переносим скрипты в продакшен.pipe(gulp.dest("dist/js")) var buildHtml = gulp.src("app/*.html") // Переносим HTML в продакшен.pipe(gulp.dest("dist")); }); gulp.task("clear", function (callback) { return cache.clearAll(); }) gulp.task("watch", function() { gulp.watch("app/sass/**/*.sass", gulp.parallel("sass")); // Наблюдение за sass файлами gulp.watch("app/*.html", gulp.parallel("code")); // Наблюдение за HTML файлами в корне проекта gulp.watch(["app/js/common.js", "app/libs/**/*.js"], gulp.parallel("scripts")); // Наблюдение за главным JS файлом и за библиотеками }); gulp.task("default", gulp.parallel("css-libs", "sass", "scripts", "browser-sync", "watch")); gulp.task("build", gulp.parallel("prebuild", "clean", "img", "sass", "scripts"));

Проект-пример из данного урока вы можете посмотреть на GitHub и скачать: https://github.com/agragregra/gulp-lesson

Чтобы установить все пакеты и зависимости для скачанного примера, выполните команду npm i в папке проекта.

Помните - к любому плагину для Gulp есть хорошая документация по подключению и использованию на npmjs.com или на страничке GitHub.

Чтобы ускорить процесс фронтенд-разработки, мы автоматизируем выполнение некоторых задач с помощью сборщика Gulp.
Для этого нам понадобится пакетный менеджер NPM. Но, чтобы установить NPM, сначала надо установить Node.js.

Шаг 1. Установка Node
Заходим на официальный сайт https://nodejs.org и скачиваем рекомендованную версию.

Инсталлятор запускать с правами администратора.
После установки появятся 2 значка: Node.js и командная консоль Node.js coomand prompt. Нам они не пригодятся, так как мы не используем Node.js, а для запуска консоли есть более удобные варианты:
1. Использовать Командную консоль TotalCommander (Команды - Открыть командную консоль).
2. Зажать Shift и, кликнув правой кнопкой, открыть контекстное меню. В нем появится пункт "Открыть окно команд".
Запуск коммандной строки лучше производить, находясь в директории нужного вам проекта, в консоли сразу отобразится путь к нужной директории, это избавит от необходимости вводить путь вручную.

Для проверки версий node и npm наберите в командной строке
node -v и нажмите Enter
затем npm -v

Версии NPM обновляются обычно чаще, чем версии node, чтобы установить последнюю версию:
npm install npm@latest -g

Комманды npm, которые нам пригодятся :
npm list - список всех установленных пакетов
npm -g ls --depth=0 - список глобально установленнных пакетов
npm outdated проверить, не устарели ли пакеты
npm update gulp - обновление версий плагинов
npm init - создать package.json
npm install package_name - установить пакет (package_name - название нужного пакета)
npm install package_name --save-dev - установить пакет и вносит запись о нем в package.json в секцию devDependencies
npm uninstall package_name - удаление пакета
npm install - установить все пакеты, перечисленные в package.json
Перед запуском в продакшн npm shrinkwrap - фиксируем версии пакетов,теперь npm install будет устанавливать именно их и вы будете уверены что все будет работать как надо

Сокращения
-v: --version
-g: --global
-S: --save
-D: --save-dev
-y: --yes
-n: --yes false

Шаг 2. Установка gulp
Сначала gulp надо установить глобально.

Запускаем командную консоль.
Иногда на некоторых ресурсах перед коммандой стоит значок доллара, например
$ npm install --global gulp-cli

Значок доллара не копировать, вставлять только саму комманду
npm install --global gulp-cli

Подсказка: чтобы вставлять скопированный текст в командную строку, открыть ком.строку, нажать ALT + SPACE -> Значения по умолчанию, поставить галочку Выделение мышью. Теперь можно выделить текст мышкой, скопировать, в ком. строке кликнуть правой кнопкой - текст вставится автоматически.

Шаг 3. Работа с gulp в конкретном проекте

3.1 Сначала создадим пакет зависимостей package.json
Файл package.json содержит информацию, которую мы внесем в терминале и список всех пакетов, которые мы используем в проекте.

При установке пакета с ключом --save-dev, пакет автоматически добавляется в package.json. Чтобы не устанавливать в каждом новом проекте все пакеты вручную, мы будем использовать уже готовый package.json с небходимыми нам модулями и зависимостями, расположив его в корне нашего проекта.

package.json генерируется с помощью команды npm init, которая выведет в консоль несколько вопросов для создания файла.
В пункте name по умолчанию отображается название вашего каталога с проектом.

Подсказка:
Вы можете сгенерировать это файл быстрее и проще, используя опцию --yes (автоматический ответ “да” на все вопросы):
npm init --yes

Полезно знать:
Вы можете установить значения по умолчанию, которые будут использоваться при каждом запуске npm init, а значит будут экономить вам время. После установки они сохраняются в.npmrc файлах.
Например:
npm config set init.author.name "Valentina Vladova"
npm config set init.author.email "[email protected]"
npm config set init.author.url "http://simpalmarket.com/"
npm set init-license MIT
npm set init-version 0.0.0
Затем запустить npm init, все указанные значения подтянутся в соответстующие переменные.

Когда npm init спросит про гит-репозиторий, пишите кратко user/repo — npm достаточно умён, чтобы раскрыть строчку в https://github.com/user/repo. npm также сгенерирует поля repository, bugs и homepage в нужном формате.

Итак, заходим в корневую папку проекта, вызываем командную консоль и набираем
npm init --yes

В корне проекта появится файл package.json с примерно таким содержанием

3.2 Установим gulp локально
В папке проекта в консоли вводим:
npm install --save-dev gulp

или сокращенно
npm i gulp --save-dev

В списке будут Warn - игнорируем.

Для проверки версии используем команду
gulp --version

В root-каталоге проекта появилась папка node_modules. В нее автоматически будут загружаться все модули и зависимости, которые мы будем устанавливать в проект. Папок с зависимостями может быть очень много, не смотря на то, даже если самих пакетов установлено не так уж и много. Это связано с тем, что в дополнение к основным пакетам устанавливаются программы, необходимые для корректной работы основного пакета. Ничего чистить и удалять из папки node_modules не нужно.

В файле package.json добавится запись
"devDependencies": {
"gulp": "^3.9.1"
}

Теперь можно устанавливать различные плагины для gulp.
http://gulpjs.com/plugins/
В поле поиска вводите название интересующего плагина.

Плагины можно устанавливать как по одному, например:
npm install --save-dev gulp-plumber
так и списком через пробел, например:
npm install gulp-sass gulp-plumber gulp-autoprefixer gulp-minify-css --save-dev
Плагины для установки и плагины для сборки лучше устанавливать отдельными командами

13 января 2014 в 13:42

GulpJS - фантастически быстрый сборщик проектов

  • Разработка веб-сайтов ,
  • JavaScript ,
  • Node.JS

В этой статье будет больше практики, мы соберем среду разработки фронтенда используя Jade и Stylus, запустим локальный сервер и подключим Livereload. Проект я выложил на Github , экспериментируйте.

Установка Gulp
У вас должен быть установлен Node.JS и npm.
Создадим директорию проекта, создадим структуру каталогов и установим Gulp и необходимые плагины.
Струтура проекта:
|--/assets // Компоненты |--|--/template |--|--/stylus |--|--/js |--|--/img |--/build // Каталог релиза |--/public // Каталог разработки |--package.json |--gulpfile.js
Установка:
$ mkdir assets public build assets/js assets/img assets/stylus assets/template $ touch gulpfile.js $ sudo npm install gulp -g $ npm init $ npm install gulp gulp-jade gulp-stylus gulp-livereload gulp-myth gulp-csso gulp-imagemin gulp-uglify gulp-concat connect --save-dev

В корне проекта есть файл конфигурации gulpfile.js его и будем редактировать.

Иницилизируем плагины:
var lr = require("tiny-lr"), // Минивебсервер для livereload gulp = require("gulp"), // Сообственно Gulp JS jade = require("gulp-jade"), // Плагин для Jade stylus = require("gulp-stylus"), // Плагин для Stylus livereload = require("gulp-livereload"), // Livereload для Gulp myth = require("gulp-myth"), // Плагин для Myth - http://www.myth.io/ csso = require("gulp-csso"), // Минификация CSS imagemin = require("gulp-imagemin"), // Минификация изображений uglify = require("gulp-uglify"), // Минификация JS concat = require("gulp-concat"), // Склейка файлов connect = require("connect"), // Webserver server = lr();
Задачи:
Теперь создадим первую задачу
// Собираем Stylus gulp.task("stylus", function() { gulp.src("./assets/stylus/screen.styl") .pipe(stylus({ use: ["nib"] })) // собираем stylus .on("error", console.log) // Если есть ошибки, выводим и продолжаем.pipe(myth()) // добавляем префиксы - http://www.myth.io/ .pipe(gulp.dest("./public/css/")) // записываем css .pipe(livereload(server)); // даем команду на перезагрузку css });
В Gulp мы работаем с потоком, поэтому получаем данные из gulp.src и поточно обрабатываем их.

Так же создадим задачи по обработке Jade, изображений и JS

// Собираем html из Jade gulp.task("jade", function() { gulp.src(["./assets/template/*.jade", "!./assets/template/_*.jade"]) .pipe(jade({ pretty: true })) // Собираем Jade только в папке./assets/template/ исключая файлы с _* .on("error", console.log) // Если есть ошибки, выводим и продолжаем.pipe(gulp.dest("./public/")) // Записываем собранные файлы.pipe(livereload(server)); // даем команду на перезагрузку страницы }); // Собираем JS gulp.task("js", function() { gulp.src(["./assets/js/**/*.js", "!./assets/js/vendor/**/*.js"]) .pipe(concat("index.js")) // Собираем все JS, кроме тех которые находятся в./assets/js/vendor/** .pipe(gulp.dest("./public/js")) .pipe(livereload(server)); // даем команду на перезагрузку страницы }); // Копируем и минимизируем изображения gulp.task("images", function() { gulp.src("./assets/img/**/*") .pipe(imagemin()) .pipe(gulp.dest("./public/img")) });

Для комфортной разработки создадим локальный сервер
// Локальный сервер для разработки gulp.task("http-server", function() { connect() .use(require("connect-livereload")()) .use(connect.static("./public")) .listen("9000"); console.log("Server listening on http://localhost:9000"); });
Необходимые нам выше задачи предназначены для разработки и конечно хочется отслеживать изменения файлов и иметь на сервере Livereload
Для этого создадим задачу "watch".

// Запуск сервера разработки gulp watch gulp.task("watch", function() { // Предварительная сборка проекта gulp.run("stylus"); gulp.run("jade"); gulp.run("images"); gulp.run("js"); // Подключаем Livereload server.listen(35729, function(err) { if (err) return console.log(err); gulp.watch("assets/stylus/**/*.styl", function() { gulp.run("stylus"); }); gulp.watch("assets/template/**/*.jade", function() { gulp.run("jade"); }); gulp.watch("assets/img/**/*", function() { gulp.run("images"); }); gulp.watch("assets/js/**/*", function() { gulp.run("js"); }); }); gulp.run("http-server"); });

Теперь можно запустить наш проект и посмотреть, что получилось.
$ gulp watch

Сервер доступен по адресу localhost:9000 Мы создали среду для веб-разработке проектов с помощью Stylus и Jade с Livereload. Теперь нужно собрать оптимизированный проект. Для этого создадим задачу "build"