Установка и использование Gulp. Gulp для ускорения разработки Автоматическое обновление страниц с использованием Bbrowser Sync
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
- Компилирование sass в css
- Добавление префиксов
- Сохранение файла в 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 у на с будет:
- Компилирование sass в css
- Добавление префиксов
- Сохранение файла в 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 NikolayGulp для ускорения разработки
Что такое 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
*
Содержимое может быть представлено в двух форматах: в виде уже прочитанного буфера, или же в виде родного нодовского потока. Каждая ступень галповского пайпа берет на вход такие вот файлы, делает некую трансформацию и передает на выход следующей цепочке. Последняя цепочка обычно просто сохраняет их на диск.
Pipe(gulp.dest("dist/"));
Осознание факта того, что потоки в gulp другие ведет к просветлению и пониманию, поскольку это объясняет большинство проблем и ошибок.
Рассмотрим реальный пример. Вы хотите использовать browserify для склейки ваших JS файлов. Вы идете, и находите плагин gulp-browserify . Но видите приписку, которая говорит, что плагин deprecated, т.е. Устарел.
Как хорошо воспитанный программист вы отметаете этот вариант, и идете искать, а какое же решение не устарело. Находите официальные рецепты от gulp, и видите , что browserify работает с галпом напрямую. Ну как напрямую, через прослойку , которая как раз и переводит родной нодовский поток в виниловский поток, который понимает gulp. Без него ничего бы не заработало, поскольку это разные потоки.
Если вы хотите написать свою трансформацию, то можете использовать данный шаблон .
Как видим, здесь все просто: на каждый файл будет вызываться наш обработчик, который и выполнит модификации. Мы можем делать все что захотим: изменить содержимое файла, переименовать файл, удалить файл или добавить еще пару новых файлов в поток.
Как мы помним, содержимое файла в виниловском потоке может быть представлено в виде буфера или в виде потока данных. Однако не обязательно поддерживать и то другое. Всегда можно использовать пакет