Gulp

Содержание
Введение
Установка
Проверка версии
Инструкции для Gulp (Gulpfile.js)
Организация файлов
Обработка файлов стилей в SASS
Мониторинг изменений (gulp-watch)
Gulp и PostCSS
Видеоуроки Gulp
Разбор ошибок
did you forget to signal async completion?
Похожие статьи

Введение

Gulp — это таск-менеджер для автоматического выполнения часто используемых задач (например, минификации, тестирования, объединения файлов), написанный на языке программирования JavaScript .

Программное обеспечение использует командную строку для запуска задач, определённых в файле Gulpfile.

Создан как ответвление от проекта Grunt, чтоб взять из него лучшие практики. Распространяется через менеджер пакетов NPM под MIT лицензией.

Если Вы будете копировать код с этой страницы - имейте в виду, что я ставлю кое-где лишние проблелы - исключительно для того, чтобы текст лучше помещался на экран. Смело удаляйте их.

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

Как скопировать папку с помощью Gulp
Объединить и сжать несколько css файлов в один
Как отправить файлы по ftp с помощью Gulp
Gulp series
Обработка только изменённых файлов с помощью gulp.watch().on('change')

Установка

Рассмотрим установку с помощью npm. Подразумевается, что nodejs Вы уже установили.

О том как установить npm читайте в моей статье Установка npm

О том как установить более старую версию Gulp - Установка архивной версии Gulp

$ npm install gulp-cli --global

C:\Users\ao\AppData\Roaming\npm\gulp -> C:\Users\ao\AppData\Roaming\npm\node_modules\gulp-cli\bin\gulp.js + gulp-cli@2.2.0 updated 7 packages in 7.386s

Установка

Проверить версию gulp

gulp -v

CLI version: 2.2.0 Local version: Unknown

Про установку не последней, а какой-то определённой версии Gulp читайте здесь

Теперь нужно перейти в директорию, в которой Вы планируете работать. Я буду делать сайт www.HeiHei.ru поэтому перехожу в директорию

$ cd /c/Users/ao/Desktop/Sites/heihei

Затем переходим непосредственно к установке gulp в текущий проект

$ npm install gulp --save-dev

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

Подробнее docs.npmjs.com

Посмотрим, как изменился наш файл package.json

Подробнее о том, зачем этот файл нужне читайте в статье npm

vi package.json

{ "name": "heihei", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { "jquery": "^3.4.1", "normalize.css": "^8.0.1" }, "devDependencies": { "gulp": "^4.0.2" }, "repository": { "type": "git", "url": "git+https://github.com/ao/heiheiru.git" }, "bugs": { "url": "https://github.com/ao/heiheiru/issues" }, "homepage": "https://github.com/ao/heiheiru#readme" }

Появился раздел devDependencies, в который в будущем я добавлю ещё довольно много пакетов.

Если теперь посмотреть содержимое папки node_modules можно увидеть, что установка Gulp добавила не одну папку, как, например, сделал бы jquery а несколько десятков.

Старые версии npm создавали всегда одну папку и размещали все зависимости туда.

Новые версии npm сохраняют зависимости в родительскую папку node_modules.

Установка более старой версии

Иногда бывает нужно установить не текущую, а более ранню версию Gulp.

Особенно это касается версии 3.9.1 , которая сильно отличается от 4 и выше.

Сделать это можно добавив нужную версию после @

npm install gulp@3.9.1 --save-dev

npm install gulp-cli@1.2.1 --save-dev

Список версий Gulp находится здесь , Gulp-cli - здесь . Нужно открыть вкладку Versions

Если Вы хотите сперва удалить Вашу версию Gulp а уже потом установить другую - сделать это можно командой uninstall

npm uninstall gulp

Gulpfile.js

После установки Gulp нужно в корневой директории проекта (в моём случае - heiheiru) создать файл gulpfile.js в который мы будем записывать инструкции для Gulp.

Первым делом запишем туда

const gulp = require('gulp');

Начиная с верси 4.0 можно пользоваться новым синтаксисом JavaScript (ES2015+)

import gulp from 'gulp'

Но для этого нужно устанавливать babel и следить чтобы не было ошибок. Я видел на форумах жалобы, сам пока не пробовал.

Подробности www.npmjs.com

После того как файл gulpfile.js создан можно запустить Gulp

gulp

Результатом будет похожее сообщение

[11:22:35] Using gulpfile ~\Desktop\Sites\heihei\gulpfile.js [11:22:35] Task never defined: default [11:22:35] To list available tasks, try running: gulp --tasks

Gulp жалуется на то, что не определно задание по умолчанию - default task

Нужно его определить

vi gulpfile.js

const gulp = require('gulp'); gulp.task('default', function() { console.log("Gulp is running!"); });

gulp

default запустится но теперь Gulp пожалуется на непонятное закрытие.

[11:31:44] Using gulpfile ~\Desktop\Sites\heihei\gulpfile.js [11:31:44] Starting 'default'... Gulp is running! [11:31:44] The following tasks did not complete: default [11:31:44] Did you forget to signal async completion?

Эту ошибку можно устранить несколькими способами. Подробности здесь. Я пользуюсь следующим:

const gulp = require('gulp'); gulp.task('default', function(cb) { console.log("Gulp is running!"); cb() });

gulp

Организация файлов

Чтобы не создавать каши из файлов и папок организуем всё правильно с самого начала.

Корневая папка носит называние проекта. В моё случае heihei или heiheiru

В этой папке мы инициализируем GIT и npm.

npm создаст папку node_modules и файлы package.json , package-lock.json.

Для GIT мы сами рано или поздно создадим файл gitignore

Так как мы будем пользоваться Gulp появится и файл gulpfile.js

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

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

Чтобы хранить эти файлы нам будет нужна папка, назовём её gulp и создадим в корневой. Внутри неё создадим подпапку tasks

Всё, что относится непосредственно к сайту положим в папку heiheiru/app

index.html положим в корень app а .css файлы, картинки и скрипты мы положим в папки heiheiru/app/assets/styles heiheiru/app/assets/images , heiheiru/app/assets/scripts

Так будет выглядить дерево папок в редакоторе Sublime

Как организовать папки для веб разработки

Примеры использования Gulp

Простые примеры

Как скопировать папку с помощью Gulp

Как объединить .css файлы в один и уменьшить их с помощью Gulp

Более сложный пример - Как отправлять файлы по ftp с помощью Gulp

Самый сложный пример - Отправить только измененённые файлы с помощью Gulp

Обработка файлов стилей

При разработке удобно пользоваться метаязыками, например, SASS.

Установим его с помощью npm

npm install gulp-sass --save-dev

Теперь можно объявить переменную sass и пользоваться этим препроцессором

const gulp = require('gulp'); const sass = require('gulp-sass'); const browserSync = require( 'browser-sync' ).create(); gulp.task('default', function(done) { console.log("Gulp is running!"); done(); }); // compile scss into css function style() { // 1. указываем расположение .scss файлов return gulp.src('./scss/**/*.scss') // 2. пропускаем их через sass compiller .pipe(sass()) // 3. указываем CSS файл, в который запишется результат? .pipe(gulp.dest( './css/style.css' ) ) } exports.style = style;

const и let - были введены в JavaScript начиная с ES6 и для современного JavaScript являются более предпочтительным вариантом чем var

gulp-watch

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

Начнём с простого - делаем функцию, которая при каждом изменении файла index.html в папке app будет выводить предупреждение.

Как это выглядит в Gulp 4

// Подтягиваем gulp // gulp-watch можно не подтягивать // - он влючен в Gulp начиная с 4-й версии const gulp = require('gulp'); // пишем функцию, выводящую в лог предупреждение function html() { console.log("Кто-то отредактировал index.html!"); } // Пишем функцию, // которая следит за файлом index.html // можно назвать её просто watch, но в образовательных // целях я назову её watchFiles // зачем - будет видно чуть ниже - в exports function watchFiles() { gulp.watch( "./app/assets/index.html", html); } // Чтобы обращаться к нашим функция извне, // например, из GitBash запишем exports // Слева запишем названия видимые извне, // а справа имена наших функций exports.html = html; exports.watch = watchFiles; // - он влючен в Gulp начиная с 4-й версии const gulp = require('gulp'); // пишем функцию, выводящую в лог предупреждение function html() { console.log("Кто-то отредактировал index.html!"); } // пишем функцию, которая следит за файлом index.html // можно назвать её просто watch, но в образовательных // целях я назову её watchFiles // зачем - будет видно чуть ниже - в exports function watchFiles() { gulp.watch( "./app/assets/index.html", html); } // Чтобы обращаться к нашим функция извне, // например, из GitBash запишем exports // Слева запишем названия видимые извне, // а справа имена наших функций exports.html = html; exports.watch = watchFiles;

Чтобы запустить мониторинг пишем

gulp watch

[20:12:19] Using gulpfile ~\Desktop\Sites\heihei\gulpfile.js
[20:12:19] Starting 'watch'...

Теперь вносим изменения в файл index.html и сохраняем

[20:14:28] Starting 'html'...
Кто-то отредактировал index.html!

Как это выглядело в Gulp 3

// Подтягиваем gulp и gulp-watch const gulp = require('gulp') watch = require('gulp-watch'); gulp.task('html', function() { console.log( "Кто-то отредактировал index.html!"); } gulp.task('watch', function() { watch( './app/assets/index.html', function() { gulp.start('html'); }); });

Создадим папку /app/assets/styles/ , в которой будут файлы .css для разработки

Напишем функцию, которая будет собирать все файлы .css из этой папки, обрабатывать их с помощью sass и соединять в один файл /app/temp/styles/style.css

Мы уже писали такую функцию выше, просто немного изменим её.

Добавим мониторинг файлов CSS gulp.watch( "./app/assets/styles/**/*.css", style);

function style() { console.log( "style is running!" ); // 1. return gulp.src( './app/assets/styles/*.css' ) // 2. pass that file through sass compiller .pipe(sass()) // 3. where do I save the compiled CSS? .pipe( gulp.dest( './app/temp/styles/style.css' ) ) } function watchFiles() { gulp.watch( "./app/assets/index.html", html ); gulp.watch( "./app/assets/styles/**/*.css", style ); }

Теперь как только мы отредактируем один из файлов стилей watch заметит это изменение, пропустит его через sass, соберет все файлы в один.

Зачем нужен SASS:

чтобы пользоваться css переменными. Создать переменную, которую потом вставлять в .css пропускать через sass compiler и когда вдруг везде нужно будет изменить значение этой переменной, например, на сайте изменится основной цвет, всё что нам нужно будет сделать - это поменять одну переменную в одном файле.

чтобы делать вложения в стилях (nested css)

чтобы использовать mixins

PostCSS

До этого Вы уже прочитали про препроцессор SASS, который наряду с LESS и Stylus является стандартом для многих проектов.

Я не пользуюсь ими, а предпочитаю более современный PostCSS, который имеет более модульную структуру, и соответственно более гибкий в настройке и быстрый

Какой бы пре или пост процессор Вы не выбрали, нужно освоить работу с ним, научиться выполнять простые задачи и переходить к более сложным задачам, таким как Обработка только изменённых файлов с помощью gulp.watch().on('change')

Подробнее про PostCSS Вы можете прочитать в статье PostCSS.

Советую разобраться с PostCSS и возвращаться в эту статью либо в одну из следующих, более продвинутых глав.

Я не стал размещать описание работы с PostCSS здесь, потому что его можно запускать не только с помощью Gulp

Видеоуроки Gulp

Видео много весят, поэтому я выделил для них отдельную страницу - Видеоуроки Gulp

Ошибки

SKIPPING OPTIONAL DEPENDENCY: fsevents

Ошибка при установке gulp. Вы выполняете

$ npm install gulp --save-dev

А на выходе

npm WARN saveError ENOENT: no such file or directory, open 'C:\Users\ao\Desktop\Sites\heihei\package.json'
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\ao\Desktop\Sites\heihei\package.json'
npm WARN heihei No description
npm WARN heihei No repository field.
npm WARN heihei No README data

npm WARN heihei No license field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ gulp@4.0.2
added 314 packages from 217 contributors and audited 6490 packages in 30.037s
found 0 vulnerabilities

Скорее всего Вы не инициализировали npm. Нужно выполнить

npm init

Ввести нужные данные (либо просто нажимать Enter), после чего создастся файл package.json и можно будет вернуться к установке gulp

Unhandled 'error' event

events.js:174 throw er; // Unhandled 'error' event
^
CssSyntaxError: postcss-simple-vars: C:\Users\ao\Desktop\Sites\travel-site\app\assets\styles\modules\_large-hero.css:5:2: Undefined variable $aMadeUpVariable2

Может быть вызвана, например, несуществующей переменной. Допустим Вы добавили цвет как переменную, но нигде её не задали.

Unexpected identifier

Если Вы запустили Gulp

gulp

И получили что-то похожее

SyntaxError: Unexpected identifier
      at Module._compile (internal/modules/cjs/loader.js:723:23)

      at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)

      at Module.load (internal/modules/cjs/loader.js:653:32)

      at tryModuleLoad (internal/modules/cjs/loader.js:593:12)

      at Function.Module._load (internal/modules/cjs/loader.js:585:3)

      at Module.require (internal/modules/cjs/loader.js:692:17)

      at require (internal/modules/cjs/helpers.js:25:18)

      at execute (C:\Users\ao\AppData\Roaming\npm\
node_modules\gulp-cli\lib\versioned\^4.0.0\index.js:36:18)

      at Liftoff.handleArguments (C:\Users\ao\AppData\Roaming\npm\
node_modules\gulp-cli\index.js:201:24)

      at Liftoff.execute (C:\Users\ao\AppData\Roaming\npm\
node_modules\gulp-cli\node_modules\liftoff\index.js:201:12)

Скорее всего Вы пытаетесь использовать синтаксис ES2015+ и не установили babel или он работает но с ошибкой.

Здесь два выхода - разобраться и настроить либо перейти к старому синтаксису с require

Did you forget to signal async completion?

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

Эту ошибку можно устранить несколькими способами. Я пользуюсь самым простым - в таске использую не анонимную функцию а называю функцию, например cb (от слова callback), а в конце таска вызваю её без аргументов:

const gulp = require('gulp'); gulp.task('default', function(cb) { console.log("Gulp is running!"); cb(); });

5

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

Это предупреждение о несовместимости пакета fsevents с Windows, как Вы можете убедиться здесь fsevents нужен для работы с iOS поэтому можно просто проигнорировать.

Error - Task function must be specified

Эту ошибку я разбираю в статье Gulp series

No PostCSS Config found in

Эту ошибку я разбираю в статье Postcss