Android Linux Windows

Установка и использование Gulp. Gulp для ускорения разработки Автоматическое обновление страниц с использованием Bbrowser Sync

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"

Npm init

От вас потребуется:

  • Указать название проекта
  • Версию проекта
  • Описание проекта
  • Точку входа
  • Команду
  • Git репазиторий
  • Ключевые слова
  • Имя автора
  • Лицензия

Npm i –g gulp

  • Название задачи

Gulp test

Задача работает.

Gulp serve

Npm i gulp-sass --save-dev

  1. Компилирование sass в css
  2. Добавление префиксов
  3. Сохранение файла в src/css

Создание задачи в gulp

Вывод.

https://gulpjs.com/plugins/

Открываем терминал и переходим в папку с проектом. Первое, что нам необходимо сделать это инициализировать npm для этого выполняем команду:

Npm init

От вас потребуется:

  • Указать название проекта
  • Версию проекта
  • Описание проекта
  • Точку входа
  • Команду
  • Git репазиторий
  • Ключевые слова
  • Имя автора
  • Лицензия

Все можно оставить по умолчанию (если вы не хотите выкладывать проект в общий доступ)

Затем подтверждаем введенную информацию.

Отлично. NPM инициализировали. Теперь в корне появился файл packages.json – файл конфигурации менеджера пакетов.

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

Npm i –g gulp

Теперь установим gulp для проекта:

Npm install --save-dev gulp

Все gulp для проекта установлен.

Давайте проверим. Создадим файл gulpfile.js и создадим в нем одну задачу test, которая будет выводить в консоль «Я работаю».

Var gulp = require("gulp"); gulp.task("test", function() { console.log("Я работаю"); });

Первое мы подключаем gulp, и второе мы вызываем функцию task у gulp, которая принимает два параметра:

  • Название задачи
  • Анонимная функция в которой описывается наша задача

Теперь в консоли выполните следующую команду

Gulp test

Задача работает.

Теперь давайте установим и подключим пакеты, которые помогают при верстке.

Browsersync, пакет который позволяет при изменении файлов обновлять страницу автоматически

Для установки в консоли выполняем следующую команду:

Npm i browser-sync --save-dev

Теперь давайте создадим задачу, которая будет запускать browser-sync и отслеживать изменения файлов.

Gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/css/*.css")on("change", browserSync.reload); gulp.watch("src/*.html").on("change", browserSync.reload); });

Задача называется serve. И browser-sync будет обновлять страницу браузера автоматически, если изменились файлы с расширением css (которые расположены в папке src/css) и с расширением html (которые расположены в папке src).

Для запуска данной задачи выполняем команду

Gulp serve

Для верстки я использую sass. Поэтому для компиляции из sass в css я использую пакет gulp-sass.

Установка и настройка gulp-sass

Для установки gulp-sass в консоли выполняем команду:

Npm i gulp-sass --save-dev

Теперь создадим задачу sass, которая будет компилировать sass в css. И изменим задачу serve, чтобы наш browser-sync отслеживал вместо css файлы sass.

Var gulp = require("gulp"); var browserSync = require("browser-sync").create(); var sass = require("gulp-sass"); gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/sass/*.sass", ["sass"]); gulp.watch("src/*.html").on("change", browserSync.reload); }); gulp.task("sass", function() { return gulp.src("src/sass/*.sass") .pipe(sass().on("error", sass.logError)) .pipe(gulp.dest("src/css")) .pipe(browserSync.stream()); });

Теперь при запуске задачи serve, будет запускаться задача sass.

Установка и настройка gulp-autoprefixer

Для установки gulp-autoprefixer выполним команду:

Npm i gulp-autoprefixer --save-dev

И добавим в задачу sass добавление префикса.

Var gulp = require("gulp"); var browserSync = require("browser-sync").create(); var sass = require("gulp-sass"); var autoprefixer = require("gulp-autoprefixer"); gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/sass/*.sass", ["sass"]); gulp.watch("src/*.html").on("change", browserSync.reload); }); gulp.task("sass", function() { return gulp.src("src/sass/*.sass") .pipe(sass().on("error", sass.logError)) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(gulp.dest("src/css")) .pipe(browserSync.stream()); });

Теперь при запуске задачи sass у на с будет:

  1. Компилирование sass в css
  2. Добавление префиксов
  3. Сохранение файла в src/css

Следующий пакет объединяет все css файлы в один.

Установка и настройка contactCss

Для установки contactCss используем следующую команду:

Npm i gulp-concat-css --save-dev

И добавим выполнение данного пакета в задачу sass. (Будем все файлы css объединять в style.css)

Var gulp = require("gulp"); var browserSync = require("browser-sync").create(); var sass = require("gulp-sass"); var autoprefixer = require("gulp-autoprefixer"); var concatCss = require("gulp-concat-css"); gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/sass/*.sass", ["sass"]); gulp.watch("src/*.html").on("change", browserSync.reload); }); gulp.task("sass", function() { return gulp.src("src/sass/*.sass") .pipe(sass().on("error", sass.logError)) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(concatCss("style.css")) .pipe(gulp.dest("src/css")) .pipe(browserSync.stream()); });

Отлично. Теперь добавим пакет, который переименовывает файлы. (Он нам понадобится, кода мы будем минимизировать css, и js файлы)

Установка и настройка gulp-rename

Для установки gulp-rename выполним следующую команду:

Npm i gulp-rename --save-dev

Пока данный пакет не будем добавлять ни в какие задачи.

Установка и настройка пакета для минимизации CSS файлов – clean-css

Для установки clean-css выполним следующую команду:

Npm i gulp-clean-css --save-dev

Теперь давайте создадим задачу mincss, которая будет добавлять к имени файла суффикс «.min», минимизировать css файл и сохранять в app/css

Var gulp = require("gulp"); var browserSync = require("browser-sync").create(); var sass = require("gulp-sass"); var autoprefixer = require("gulp-autoprefixer"); var concatCss = require("gulp-concat-css"); var cleanCSS = require("gulp-clean-css"); var rename = require("gulp-rename"); gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/sass/*.sass", ["sass"]); gulp.watch("src/*.html").on("change", browserSync.reload); }); gulp.task("sass", function() { return gulp.src("src/sass/*.sass") .pipe(sass().on("error", sass.logError)) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(concatCss("style.css")) .pipe(gulp.dest("src/css")) .pipe(browserSync.stream()); }); gulp.task("mincss", function() { return gulp.src("src/css/*.css") .pipe(rename({suffix: ".min"})) .pipe(cleanCSS()) .pipe(gulp.dest("app/css")); })

Отлично, давайте установим gulp пакет, который будет минимизировать js файлы.

Установка и настройка пакета gulp для минимизации js файлов —gulp-uglify

Для установки gulp-uglify выполним следующую команду:

Npm i gulp-uglify --save-dev

Теперь создадим задачу, которая будет добавлять к файлу суффикс «.min», минимизировать файл js и сохранять в app/js

Var gulp = require("gulp"); var browserSync = require("browser-sync").create(); var sass = require("gulp-sass"); var autoprefixer = require("gulp-autoprefixer"); var concatCss = require("gulp-concat-css"); var cleanCSS = require("gulp-clean-css"); var rename = require("gulp-rename"); var uglify = require("gulp-uglify"); gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/sass/*.sass", ["sass"]); gulp.watch("src/*.html").on("change", browserSync.reload); }); gulp.task("sass", function() { return gulp.src("src/sass/*.sass") .pipe(sass().on("error", sass.logError)) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(concatCss("style.css")) .pipe(gulp.dest("src/css")) .pipe(browserSync.stream()); }); gulp.task("mincss", function() { return gulp.src("src/css/*.css") .pipe(rename({suffix: ".min"})) .pipe(cleanCSS()) .pipe(gulp.dest("app/css")); }) gulp.task("minjs", function() { return gulp.src("src/js/*.js") .pipe(rename({suffix: ".min"})) .pipe(uglify()) .pipe(gulp.dest("app/js")); })

Мы создали основные задачи. Но две последние должны выполняться при выкладывании проекта в продакшен. И выполняться должны вместе. Давайте создадим задачу, которая будет выполнять задачу mincss, а потом minjs

Создание задачи в gulp

Создадим задачу min, которая будет запускать задачи mincss и minjs

Var gulp = require("gulp"); var browserSync = require("browser-sync").create(); var sass = require("gulp-sass"); var autoprefixer = require("gulp-autoprefixer"); var concatCss = require("gulp-concat-css"); var cleanCSS = require("gulp-clean-css"); var rename = require("gulp-rename"); var uglify = require("gulp-uglify"); gulp.task("serve", ["sass"], function() { browserSync.init({ server: "src/" }); gulp.watch("src/sass/*.sass", ["sass"]); gulp.watch("src/*.html").on("change", browserSync.reload); }); gulp.task("sass", function() { return gulp.src("src/sass/*.sass") .pipe(sass().on("error", sass.logError)) .pipe(autoprefixer({ browsers: ["last 2 versions"], cascade: false })) .pipe(concatCss("style.css")) .pipe(gulp.dest("src/css")) .pipe(browserSync.stream()); }); gulp.task("mincss", function() { return gulp.src("src/css/*.css") .pipe(rename({suffix: ".min"})) .pipe(cleanCSS()) .pipe(gulp.dest("app/css")); }) gulp.task("minjs", function() { return gulp.src("src/js/*.js") .pipe(rename({suffix: ".min"})) .pipe(uglify()) .pipe(gulp.dest("app/js")); }) gulp.task("min",["mincss", "minjs"]);

Все. Давайте еще зададим задачу по умолчанию.

Задание задачи по умолчанию gulp

gulp.task("default", ["serve"]);

Вывод.

Мы с вами рассмотрели для чего нужен gulp, как его установить. Установили дополнительные пакеты, которые необходимы для верстки и задали задачи.

Вы можете самостоятельно находить необходимые пакеты на сайте https://gulpjs.com/plugins/ и устанавливать их. А затем создавать задачи для оптимизации процесса разработки.

Soldatov Nikolay

Gulp для ускорения разработки

Что такое Gulp, зачем он нужен, его возможности, как установить и как начать использовать в разработке сайтов. Обновление до Gulp 4

Gulp - что это такое и зачем он нужен

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

Gulp таск имеет следующий вид:

// Gulp 3 gulp . task (" имя-таска " ,[ " имя-другого-таска " ], function () { таск (и ) }); // Gulp 4 gulp . task (" имя-таска " , gulp . parallel (" имя-другого-таска " ), function () { таск (и ) });

["имя-другого-таска"] или gulp.parallel("имя-другого-таска") - это необходимо писать в том случае, если до выполнения нашего таска нужно выполнить другой таск(и).

Создадим простейший task, который будет выводить строку "Привет, Мир!".

gulp . task (" output " , function () { console . log (" Привет, Мир! " ); });

"output" - имя таска, оно может быть любым.

Для вызова таска нужно выполнить команду gulp имя-таска (в нашем случае output ). Сделаем это.

Запуск gulp таска по умолчанию

Таск будет выполнять все перечисленные в ней таски одной командой gulp

// Gulp 3 gulp . task (" default " , [ " output " ]); // Gulp 4 gulp . task (" default " , gulp . parallel (" output " ));

И теперь чтобы запустить наш таск, достаточно просто написать gulp

В нашем примере указан один таск, но можно перечислить все необходимые задачи следующим образом:

// Gulp 3 gulp . task (" default " , [ " output " , " other-task-1 " , " other-task-2 " ]); // Gulp 4 gulp . task (" default " , gulp . parallel (" output " , " other-task-1 " , " other-task-2 " ));

Это был самый простой пример работы Gulp. Для более сложных задач используются дополнительные методы.

Методы gulp

gulp.task - создание таска

gulp.src - какие файлы использовать для обработки плагином

gulp.watch - наблюдение за изменениями в файлах

.pipe(plugin()) - обращение к плагину для обработки файлов

.pipe(gulp.dest("путь")) - куда записать (выгрузить) файл после выполнения задачи

Gulp 4

Если у вас не работает Gulp , возможно вы обновили его с 3 версии до Gulp 4 в пакетном менеджере npm. В связи с этим появились ошибки в gulpfile.js из-за измений в синтаксисе выполнения gulp тасков

Все конструкции с квадратными скобками "[" "]" нужно заменить на gulp.parallel()

// у вас было: gulp . task (" watch " , [ " sass " , " js " , " browser-sync " ], function () { gulp . watch (" sass/**/*.sass " , [ " sass " ]); gulp . watch ([ " libs/**/*.js " , " js/common.js " ], [ " js " ]); gulp . watch (" *.html " , browsersync . reload ) }); gulp . task (" default " , [ " watch " ]); // нужно изменить на: gulp . task (" html " , function () { return gulp . src (" *.html " ) . pipe (browserSync . reload ({ stream : true })) }); gulp . task (" watch " , gulp . parallel (" sass " , " js " , " browser-sync " ), function () { gulp . watch (" sass/**/*.sass " , gulp . parallel (" sass " ); gulp . watch ([ " libs/**/*.js " , " js/common.js " ], gulp . parallel (" js " )); gulp . watch (" *.html " , gulp . parallel (" html " )) }); gulp . task (" default " , gulp . parallel (" watch " ));

Чтобы ускорить процесс фронтенд-разработки, мы автоматизируем выполнение некоторых задач с помощью сборщика 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
Плагины для установки и плагины для сборки лучше устанавливать отдельными командами

Всем привет. Если вы связаны хоть как-то с 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. Без него ничего бы не заработало, поскольку это разные потоки.

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

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