Приятная сборка frontend проекта. Разбираемся со сборкой front end на Gulp. Альтернативы gulp и grunt

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

Что такое Gulp?

Gulp - это инструмент сборки front-a. Он позволяет автоматизировать повторяющиеся задачи (сборка и минификация CSS- и JS-файлов, запуск тестов, перезагрузка браузера и другие). Тем самым Gulp ускоряет и оптимизирует процесс веб-разработки.

Установка Gulp

Установить Gulp достаточно легко. Если у вас что-то не получится, пишите в комментариях или загуглите вашу проблему. Итак для установки нужно сделать 3 шага:

  • Установить Gulp глобально
  • Установить Gulp как devDependencies (зависимости для разработки)
  • Создать файл gulpfile.js

Первый шаг - устанавливаем глобально Gulp. Открываем терминал и пишем:

npm install --global gulp

После этого вам нужно установить Gulp как devDependencies для вашего проекта. Убедитесь в том, что у вас есть файл package.json . Если его нет, то создайте его написав в консоль npm init . Теперь можно установить Gulp как devDependencies:

npm install --save-dev gulp

И наконец, вам нужно создать gulpfile.js в корне вашего проекта, который будет содержать ваши задачи (tasks). В качестве промежуточного шага, мы установим плагин gulp-util . Чтобы показать как устанавливаются плагины:

npm install --save-dev gulp-util

Теперь настало время написать нашу первую задачку. Открываем только что созданный файл gulpfile.js и пишем в него следующее:

/* File: gulpfile.js */ // собираем все наши плагины var gulp = require (" gulp " ), gutil = require (" gulp-util " ); // создаем задачку, которая будет выполняться по умолчанию gulp . task (" default " , function () { return gutil . log (" Gulp is running! " ) });

И теперь нам остается запустить gulp в терминале и мы увидим нечто похожее на это:

> gulp [ 12:32:08] Using gulpfile ~/Projects/gulp-scotch-io/gulpfile.js [ 12:32:08] Starting "default" ... [ 12:32:08] Gulp is running! [ 12:32:08] Finished "default" after 1 ms

Обзор

Сам по себе Gulp очень скуден на возможности. Но все, что вам нужно вынесено в отдельные плагины. Они совместно с Gulp творят чудеса.

Api у gulp очень маленькое, и содержит всего 4 функции высшего порядка:

  • gulp.task
  • gulp.src
  • gulp.dest
  • gulp.watch

gulp.task определяет наши задачи. В качестве аргументов принимает название, зависимости (массив) и функцию (основные действия). Зависимостей может и не быть:

gulp . task (" mytask " , function () { //сделать что-то }); gulp . task (" dependenttask " , [ " mytask " ], function () { //сделать что-то после того, как "mytask" будет выполнен });

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

gulp.dest указывает на папку, в которую мы хотим сохранить измененные файлы.

gulp.src и gulp.dest используется для простой копии файлов:

gulp . task (" copyHtml " , function () { // скопировать все html файлы из source/ в public/ gulp . src (" source/*.html " ). pipe (gulp . dest (" public " )); });

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

Сжатие изображение, JS и CSS файлов, в целях оптимизации загрузки веб-страниц и многоe многое другое. Чтобы упросить этот процесс, мы предлагаем вам воспользоваться сборкой проектов Gulp 4, которую постоянно совершенствует Андрей Горохов. Ниже будут представлены ссылки на скачивание, а пока пройдемся по основным моментам: описанию и установке.

Сборщик проектов Gulp

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

Скачать сборку можно с репозитория Github или через командную строку Git . В дальнейшем вы сможете настроить её под свои задачи.

Особенности

  • именование классов по БЭМ
  • используется БЭМ-структура
  • используется препроцессор SCSS
  • используется транспайлер Babel для поддержки современного JavaScript (ES6) в браузерах
  • используется Webpack для сборки JavaScript-модулей
  • используется CSS-сетка smart-grid на основе Bootstrap для быстрой адаптивной вёрстки
  • используется жёсткий кодгайд

Установка

  • установите NodeJS (если требуется) и Yarn
  • скачайте сборку с помощью Git : git clone https://github.com/andreyalexeich/gulp-scss-starter.git
  • установите gulp глобально: yarn global add gulp-cli
  • перейдите в скачанную папку со сборкой: cd gulp-scss-starter
  • скачайте необходимые зависимости: yarn
  • чтобы начать работу, введите команду: yarn run dev (режим разработки)
  • чтобы собрать проект, введите команду yarn run build (режим сборки)

Если вы всё сделали правильно, у вас должен открыться браузер с локальным сервером. Режим сборки предполагает оптимизацию проекта: сжатие изображений, минифицирование CSS и JS-файлов для загрузки на сервер.

Если у тебя возникли проблемы с установкой, то посмотри этот ролик:

Файловая структура

gulp-scss-starter ├── dist ├── gulp-tasks ├── src │ ├── blocks │ ├── fonts │ ├── img │ ├── js │ ├── styles │ ├── views │ └── .htaccess ├── gulpfile.babel.js ├── webpack.config.js ├── package.json ├── .babelrc.js ├── .bemrc.js ├── .eslintrc.json ├── .stylelintrc ├── .stylelintignore └── .gitignore
  • Корень папки:
    • .babelrc.js - настройки Babel
    • .bemrc.js - настройки БЭМ
    • .eslintrc.json - настройки ESLint
    • .gitignore – запрет на отслеживание файлов Git’ом
    • .stylelintrc - настройки Stylelint
    • .stylelintignore – запрет на отслеживание файлов Stylelint’ом
    • gulpfile.babel.js - настройки Gulp
    • webpack.config.js - настройки Webpack
    • package.json - список зависимостей
  • Папка src — используется во время разработки:
    • БЭМ-блоки: src/blocks
    • шрифты: src/fonts
    • изображения: src/img
    • JS-файлы: src/js
    • страницы сайта: src/views/pages
    • SCSS-файлы: src/styles
    • HTML-файлы: src/views
    • конфигурационный файл веб-сервера Apache с настройками gzip (сжатие без потерь): src/.htaccess
  • Папка dist — папка, из которой запускается локальный сервер для разработки (при запуске yarn run dev)
  • Папка gulp-tasks — папка с Gulp-тасками

Команды

  • yarn run lint:style — проверить SCSS-файлы. Для VSCode необходимо установить плагин . Для WebStorm или PHPStorm необходимо включить Stylelint в Languages & Frameworks - Style Sheets - Stylelint (ошибки будут исправлены автоматически при сохранении файла)
  • yarn run lint:style --fix — исправить ошибки в SCSS-файлах
  • yarn run dev — запуск сервера для разработки проекта
  • yarn run build — собрать проект с оптимизацией без запуска сервера
  • yarn run build views — скомпилировать Pug-файлы
  • yarn run build styles — скомпилировать SCSS-файлы
  • yarn run build scripts — собрать JS-файлы
  • yarn run build images — собрать изображения
  • yarn run build webp — сконвертировать изображения в формат.webp
  • yarn run build sprites — собрать спрайты
  • yarn run build fonts — собрать шрифты
  • yarn run build favicons — собрать фавиконки
  • yarn run build gzip — собрать конфигурацию Apache

Компонентный подход к разработке сайтов

  • аждый БЭМ-блок имеет свою папку внутри src/blocks/modules
  • папка одного БЭМ-блока содержит в себе один HTML-файл, один SCSS-файл и один JS-файл (если у блока используется скрипт)
    • HTML-файл блока импортируется в файл src/views/index.html (или в необходимый файл страницы, откуда будет вызываться блок)
    • SCSS-файл блока импортируется в файл src/blocks/modules/_modules.scss
    • JS-файл блока импортируется в src/js/import/modules.js

Пример структуры папки с БЭМ-блоком:

Blocks ├── modules │ ├──header │ │ ├── header.html │ │ ├── header.js │ │ ├── header.scss

Чтобы вручную не создавать соответствующие папку и файлы, достаточно в консоли прописать команду bem create my-block — для создания папки БЭМ-блока, где my-block — имя БЭМ-блока

Страницы проекта

  • страницы проекта находятся в папке src/views/pages
    • главная страница: src/views/index.html

Шрифты

  • шрифты находятся в папке src/fonts
    • используйте форматы .woff и.woff2
    • шрифты подключаются в файл src/styles/base/_fonts.scss
    • сконвертировать локальные шрифты можно с помощью данного сервиса

Изображения

  • изображения находятся в папке src/img
    • изображение для генерации фавиконок должно находиться в папке src/img/favicon и иметь размер не менее 1024px x 1024px
    • изображения автоматически конвертируются в формат.webp . Подробная информация по использованию .

Сторонние библиотеки

  • все сторонние библиотеки устанавливаются в папку node_modules
    • для их загрузки воспользуйтеcь командой yarn add package_name
    • для подключения JS-файлов библиотек импортируйте их в самом начале JS-файла БЭМ-блока (то есть тот БЭМ-блок, который использует скрипт), например:

    Import $ from " jquery" ;

    • для подключения стилевых файлов библиотек импортируйте их в файл src/styles/vendor/_libs.scss
    • JS-файлы и стилевые файлы библиотек самостоятельно изменять нельзя

⚠️ Если в вашем проекте используется несколько библиотек, которые необходимо подключать на нескольких страницах, во избежании ошибок нужно:

  • по пути src/js/import создать папку pages
  • в папке pages создать js-файл для страницы, например, pageA.js , и импортировать туда библиотеку, которая будет использоваться только на этой странице
    • аналогично проделать шаг для дополнительных страниц
  • в файле webpack.config.js в точку входа добавить js-файлы страниц, пример:

Entry: { main: " ./src/js/index.js" , pageA: " ./src/js/import/pages/pageA.js" , pageB: " ./src/js/import/pages/pageB.js" }

  • подключить скомпилированные js-файлы на необходимых страницах

CSS-сетка smart-grid

В сборщик включена CSS-сетка smart-grid от Дмитрия Лаврика . Она позволяет избавиться от лишних классов в разметке за счёт использования примесей в SCSS и ускоряет адаптивную вёрстку. Конфигурация уже настроена в соответствии с сеткой Bootstrap . Пример использования:

Items { @include row-flex (); @include md (justify-content , center ); .item { @include col (); @include size (3 ); @include size-md (5 ); @include size-xs (10 ); } }

В наше время сборка front-end’a является уже неким стандартом в разработке сайтов и веб-приложений. Есть множество вариантов сборки ресурсов сайта и каждый разработчик выбирает для себя сам, какие инструменты для этого использовать. Я же хочу поведать о процессе сборке с помощью менеджера задач, которому отдал предпочтение, а именно GULP.

В двух слова о Gulp

Gulp — это менеджер задач (как grunt) для сборки ресурсов и выполнения рутинных задач. Он прост в использовании. Это крайне полезный швейцарский нож и может выполнять множество функций. А самое главное он быстр.

Установка Gulp

Прежде всего для работы gulp необходимо установить node.js

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

Npm init

Установим gulp и добавим его в зависимости проекта

Npm install --save-dev gulp

Теперь необходимо создать файл в корне проекта gulpfile.js и создадим пустую задачу для примера.

Var gulp = require("gulp"); gulp.task("default", function() { // место для кода, который будет выполняться в задаче });

Собственно так и будут выглядеть задачи в gulp. Практически для каждой задачи, которую может понадобиться выполнить для сборки вашего front-end’a есть плагины. Об установке и использовании плагинов далее.

Сборка css

Думаю в наши дни уже все используют css препроцессоры. Если вы еще не используете какой-либо css препроцессор, вам срочно необходимо ознакомиться с или и начать использовать sass или less в работе.

Я предпочитаю использовать sass, поэтому покажу на примере плагина sass.

Установка плагина

Npm install gulp-sass --save-dev

Две простейших задачи для сборки и live сборки sass файлов при их изменении.

Var gulp = require("gulp"); var sass = require("gulp-sass"); //Задача для сборки gulp.task("sass", function () { return gulp.src("./sass/**/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(gulp.dest("./css")); }); //Задача, после запуска которой, gulp будет следить за изменениями файлов gulp.task("watch", function () { gulp.watch("./sass/**/*.scss", ["sass"]); });

Теперь прописав в консоли gulp sass , gulp соберет все ваши sass файлы в указанной директории.
А выполнив gulp watch запустится процесс, который будет следить за изменением sass файлов, и при изменении сразу их компилировать.

Для остановки процесса достаточно нажать на клавиатуре Ctrl + C.

Объединение JavaScript файлов

Для этого необходимо установить плагин gulp-concat .

Npm install --save-dev gulp-concat

Теперь добавим задачу в наш gulpfile.js .

Var gulp = require("gulp"); var sass = require("gulp-sass"); var concat = require("gulp-concat"); gulp.task("sass", function () { return gulp.src("./sass/**/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(gulp.dest("dist/css")); }); gulp.task("scripts", function() { return gulp.src("src/**/*.js") .pipe(concat("app.js")) .pipe(gulp.dest("dist/js")); }); gulp.task("watch", ["sass", "scripts"], function() { gulp.watch("css/**/*.sass", ["sass"]); gulp.watch("src/**/*.js", ["scripts"]); });

Обратите внимание, что задачи sass и scripts находятся в зависимостях у задачи watch.

Теперь скрипты будут объединяться по команде gulp scripts или же при gulp watch .

Минификация ресурсов

Для минификации JavaScript файлов необходимо установить плагин uglify , а для минификации sass файлов необходимо добавить опцию {outputStyle: "compressed"} .

Var gulp = require("gulp"); var sass = require("gulp-sass"); var concat = require("gulp-concat"); var uglify = require("gulp-uglify"); gulp.task("sass", function () { return gulp.src("./sass/**/*.scss") .pipe(sass({outputStyle: "compressed"}).on("error", sass.logError)) .pipe(gulp.dest("dist/css")); }); gulp.task("scripts", function() { return gulp.src("src/**/*.js") .pipe(concat("app.js")) .pipe(uglify()) .pipe(gulp.dest("dist/js")); }); gulp.task("watch", ["sass", "scripts"], function() { gulp.watch("css/**/*.sass", ["sass"]); gulp.watch("src/**/*.js", ["scripts"]); });

Версионность ресурсов

Версионность ресурсов необходима для контроля кешированных файлов в браузерах посетителей. Если вы работаете с html файлами, то имена создаваемым файлам и пути к ним можно генерировать с помощью плагина gulp-rev или gulp-rev-all . С помощью них выходят файлы файлы с именами такого типа: app-ef62e7.js .
Но когда вы работаете с движками сайтов и вам нужно в определенном файле (любого формата), в определенном месте прописать необходимые пути, то реализовать это можно таким способом.

В первую очередь установим плагины gulp-html-replace и gulp-rename .

Npm install gulp-html-replace --save-dev npm install gulp-rename --save-dev

gulp-rename — будет называть файлы, а gulp-html-replace будет прописывать пути в указанных файлах.

Имена файлов

Теперь дополним наш gulpfile новыми строками:

Var gulp = require("gulp"); var sass = require("gulp-sass"); var concat = require("gulp-concat"); var uglify = require("gulp-uglify"); var htmlreplace = require("gulp-html-replace"); var rename = require("gulp-rename"); var time = Date.now(); gulp.task("path", function () { gulp.src("/assets_tpl.php") .pipe(htmlreplace({ "js": [ "/dist/js/app-"+time+".js" ], "css": [ "/dist/css/bundle-"+time+".css" ] })) .pipe(rename("assets.php")) .pipe(gulp.dest("/")); }); gulp.task("sass",["path"], function () { return gulp.src("./sass/**/*.scss") .pipe(sass({outputStyle: "compressed"}).on("error", sass.logError)) .pipe(concat("bundle-"+time+".css")) .pipe(gulp.dest("dist/css")); }); gulp.task("scripts",["path"], function() { return gulp.src("src/**/*.js") .pipe(concat("app-"+time+".js")) .pipe(uglify()) .pipe(gulp.dest("dist/js")); }); gulp.task("watch", ["sass", "scripts"], function() { gulp.watch("css/**/*.sass", ["sass"]); gulp.watch("src/**/*.js", ["scripts"]); });

Переменная time создана для генерации уникального числа в момент инициализации gulp скрипта. В данном случае это простой timestamp. Он и будет прописываться в имя файла.

Пути к файлам

Также создана новая задача path , которая по файлу-шаблону assets_tpl.php сгенерирует файл assets.php с боевыми путями к файлам.

Вот как выглядит файл-шаблон assets_tpl.php:

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

Так же стоит обратить внимание, что задача path добавлена как зависимость для задач sass и scripts .

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

Npm install --save-dev gulp-clean

Затем добавим задачу с флагом {read: false} , для ускоренного удаления.

Var clean = require("gulp-clean"); gulp.task("clean", function () { return gulp.src("dist", {read: false}) .pipe(clean()); });

И создадим задачу build , которая будет выполнять чистку, а затем собирать все наши ресурсы.

Gulp.task("build",["clean","sass","scripts","path"], function () {});

Таким образом выполнив в консоли команду gulp build , gulp полностью автоматически соберет весь front-end для проекта. Данную команду также можно повесить на хук после деплоя проекта на сервер / хостинг.

Заключение

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

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

Таск-раннеры и системы сборки сильно ускоряют работу, автоматизируя компиляцию, тестирование и другие рутинные задачи. Как и в любой другой области, на этом рынке существует сильная конкуренция. До 2014 года среди них главенствовал таск-раннер grunt, но позже из состава проекта выделилась небольшая команда, которая решила делать альтернативный инструмент, gulp, ориентированный на сборку проекта.

Чтобы помочь вам определиться с выбором, в рамках статьи рассмотрим основные таск-менеджеры:

  • grunt

а также коснемся других средств и способов сборки.

Забегая немного вперед, скажем, что мы в WaveAccess пользуемся именно gulp. Внедрить инструмент оказалось очень легко: у семейства продуктов JetBrains (IDEA, WebStorm, ReSharper), которые мы используем уже много лет, есть отличные плагины для работы с gulp/grunt и npm/nodejs.

Таск-менеджер vs. система сборки проекта: в чем разница?

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

  • Задачи для деплоя (zip проекта, загрузка проекта на удаленный сервер и тп)
  • Задачи по сборке проекта (минификация, оптимизация, проверка кода на валидность и тп)
  • Задачи для миграции данных и т.д.

Примеры таких инструментов - grunt и gulp.

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

  • конкатенация,
  • проверка кода на валидность,
  • минификация кода, и тд.

К подобным инструментам относятся Webpack, Broccoli, Brunch, Browserify и другие.

Все подобные frontend-задачи можно автоматически выполнять при помощи других средств: к примеру, с помощью npm run, о котором мы также поговорим в статье.

Пример

Рассмотрим gulp-файл для сборки проекта:

Const gulp = require (‘gulp’); const coffee = require (‘gulp-coffee’); const concat = require (‘gulp-concat’); const uglify = require (‘gulp-uglify’); const imagemin = require (‘gulp-imagemin’); const sourcemaps = require (‘gulp-sourcemaps’); const del = require (‘del’); }

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

Var gulp = require("gulp"); var zip = require("gulp-zip"); var del = require("del"); var install = require("gulp-install"); var runSequence = require("run-sequence"); var awsLambda = require("node-aws-lambda"); gulp.task("clean", function(cb) { del(["./dist", "./dist.zip"], cb); }); gulp.task("copy", function() { return gulp.src("index.js") .pipe(gulp.dest("dist/")); }); gulp.task("node-mods", function() { return gulp.src("./package.json") .pipe(gulp.dest("dist/")) .pipe(install({production: true})); }); // Clean up all aws-sdk directories from node_modules. We don"t // need to upload them since the Lambda instance will already // have it available globally. gulp.task("clean-aws-sdk", function(callback) { del(["dist/node_modules/**/aws-sdk"], callback); }); gulp.task("zip", function() { return gulp.src(["dist/**/*", "!dist/package.json"]) .pipe(zip("dist.zip")) .pipe(gulp.dest("./")); }); gulp.task("upload", function(callback) { awsLambda.deploy("./dist.zip", require("./lambda-config.js"), callback); }); gulp.task("deploy", function(callback) { return runSequence(["clean"], ["copy"], ["node-mods"], ["clean-aws-sdk"], ["zip"], ["upload"], callback); });

A можно описывать новые задачи как комбинации уже существующих:

Gulp.task(‘deploy’, gulp.series (‘clean’, ‘copy’, ‘node-mods’, ‘clean-aws-sdk’, ‘zip’, ‘upload’));

В этом и заключается отличие. Теперь рассмотрим основные инструменты.

gulp vs. grunt

Итак, перед нами два таск-раннера: gulp и grunt. Оба используют node.js и npm, а задачи им ставят, используя javascript.

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

Потоковая передача данных

Перед нами грант-файл, который осуществляет сборку и обработку CSS.

Из него видно, что grunt при запуске каждого процесса:

    открывает файл;

    запускает процесс;

    сохраняет изменения;

    закрывает обработанный файл, чтобы предотвратить вмешательство в него следующего процесса;

    записывает файл в итоговую папку.

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

Плагины пишут разные авторы. Чтобы каждый плагин мог работать с файлами, обходя сохранение, файлы нужно представить в виде объектов. В gulp эту задачу выполняет виртуальная файловая система Vynyl-FS. И gulp сразу передает файл следующему процессу без создания временных файлов и без сохранения на диск.

Та же самая конфигурация для gulp уже компактнее:

Его общий механизм работы - потоковая обработка файлов без записи на диск:

Последовательность выполнения задач

Есть и другое отличие: gulp по умолчанию асинхронно выполняет таски. В этом есть и плюсы, и минусы. В том же конфигурационном файле мы даем команду считать файлы из директории dev/*scss и отправить их в SASS.

Потоки отправляют результат в.pipe. Метод.pipe позволяет собирать результат в буфер по частям, а когда он заполнен, сразу отправлять информацию в поток для чтения, еще не закончив получать содержимое директории.

Последовательное выполнение задач делает gulp быстрым и мощным, но изредка возникает необходимость все же выполнить задачи синхронно, как в grunt. Проблему можно решить через обратный вызов, возвращение потока или Promise . Более подробно задача разобрана на Хабре . Есть и альтернативный вариант на самом сайте npm.js

Если вы пользуетесь grunt, но вас привлекает потоковая передача данных -- тот же модуль Vynyl-FS можно использовать для ее реализации в grunt.

Лаконичное API gulp имеет всего 5 методов:

    Task(name, fn). Регистрирует функцию с именем. Можно указать зависимость от других тасков, если нужно их выполнить сначала.

    Run(tasks...). Выполняет задачи.

    Watch(glob, fn). Выполняет функцию, если файл на месте glob меняется.

    Src(glob). В качестве параметра принимает маску файлов и возвращает поток, представляющий эти файлы. Затем поток может быть передан на вход плагинам.

    Dest(folder). Сохраняет файлы в указанную папку.

Особенно хотелось бы отметить наличие.watch() в “родном” API проекта, ведь слежение за постоянными изменениями файлов является важнейшей составляющей сборки. Краткость API дает возможность этому таск-менеджеру сфокусироваться на своей основной задаче – сборке проектов.

Альтернативы gulp и grunt

Несмотря на популярность gulp (больше 130 к скачиваний в день) и grunt (более 86 к скачиваний в день согласно npmjs.com), разработчики видят в этих системах и свои недостатки: к примеру, зависимость от плагинов, неполная документация, неудобный дебаггинг. В качестве альтернативы можно рассмотреть системы сборки проектов (такие как Broccoli и Webpack) или npm-скрипты.

Системы сборки проектов

Рассмотрим несколько альтернативных решений на платформе Node.js. Для сборки проекта они могут заменить gulp и grunt.

Эта система, как и gulp, возникла как конкурент таск-раннеру grunt, однако разработчики изначально задумывали ее именно как помощник для сборки со всеми преимуществами и недостатками. Он без настроек “поймет”, что *.js - это файл со скриптами, *.coffee - это CoffeeScript; его конфиг более компактен. Однако никаких произвольных действий на этапе сборки он совершить не сможет.

Вот конфиг-файл Brunch. Он написан на CoffeeScript (можно также писать на JS):

Exports.config = files: javascripts: joinTo: "javascripts/app.js": /^app/ "javascripts/vendor.js": /^(bower_components|vendor)/ stylesheets: joinTo: "stylesheets/app.css" order: after: ["vendor/styles/helpers.css"] templates: joinTo: "javascripts/app.js"

Здесь хочется обратить внимание на операторы joinTo и order. На уровне конфига Brunch понимает, что придется собирать файлы в нужном порядке. В результате, конфиг занимает 20-30 строк.

Broccoli

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

По сравнению с gulp, инструмент Broccoli использует другие принципы:

    Ускорение сборки. Каждый плагин реализует промежуточное кэширование результатов сборки вместо частичной пересборки только нужных файлов.

    Деревья вместо файлов. Gulp лучше всего трансформирует один файл в один итоговый. Broccolli по умолчанию использует только деревья, а не файлы, и их трансформирует в другие деревья (вырожденные из одной вершины).

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

Webpack - гибкая модульная система сборки. Она обладает непривычным синтаксисом, но сама воспринимает любые синтаксисы модулей.

Понимая, что придется конкурировать с такими гигантами как gulp, создатели решили облегчить нам жизнь при разработке больших проектов. И добавили в утилиту:

    Умение автоматически строить дерево зависимостей и ресурсов.

    Удобные средства для реализации динамической подгрузки.

    Совместимость с практически любыми модулями (AMD, UMD, ES 2015, Common JS, сторонние модули на их основе).

    Совместимость с препроцессорами (SASS, Babel, Coffee Script, Type Script и т.д.).

    Live Reload (технологию асинхронной загрузки, при которой браузер обновляет не страницы целиком, а отдельные приложения).

    Возможность делить код и генерировать множество bundle-файлов, избегая создания одного тяжелого bundle.js.

    Умение оптимизировать код.

Отдельно можно отметить гибкий подход к зависимостям. Модулем может стать JS, CSS и HTML-файл, и даже JPEG с PNG. Можно использовать require(“myJSfile.js”) и require(“myCSSfile.css”), делить и использовать части артефакта повторно.

Подробнее о возможностях, конфигурации инструмента, плагинах можно найти на Github, в презентации с Fronttalks: глубокое погружение в Webpack .

npm скрипты

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

Возможности npm-скриптов

Npm-скрипты решают довольно много задач. Так, например, можно реализовать скрипты ловушек:

{ "name": "npm-scripts-example", "version": "1.0.0", "description": "npm scripts example", "scripts": { "prebuild": "echo I run before the build script", "build": "cross-env NODE_ENV=production webpack" "postbuild": "echo I run after the build script" } }

Сценарии будут загружаться по порядку согласно префиксам: prebuild, например, стартует перед build, потому что у него есть префикс pre. Соответственно, postbuild будет загружен последним. Команда npm run build запустит их в нужном порядке.

Можно вызывать один скрипт из другого, чтобы декомпозировать сложные задачи. Например, здесь задача prebuild вызывает задачу clean.

{ "name": "npm-scripts-example", "version": "1.0.0", "description": "npm scripts example", "scripts": { "clean": "rimraf ./dist && mkdir dist", "prebuild": "npm run clean", "build": "cross-env NODE_ENV=production webpack" } }

Если задача становится слишком сложной, всегда можно вызвать отдельный файл:

{ "name": "npm-scripts-example", "version": "1.0.0", "description": "npm scripts example", "scripts": { "build": "node build.js" } }

За счет стриминга gulp для задач сборки стал гораздо удобнее, чем grunt. Но его можно реализовать и через npm. В Windows и Unix стриминг делается по умолчанию, без сохранения промежуточных файлов.

К примеру, в Unix можно сделать grep содержимого файла и направить его в новый файл:

Grep ‘My Name’ bigFile.txt > linesThatHaveMyName.txt

Редирект(>)направляет нужные строки в конечный файл. Задача выполняется без сохранения промежуточных файлов.

Но есть и неудобства: нельзя оставлять комментарии в package.json. Выходом может стать создание коротких скриптов с понятными названиями, нацеленных на какую-то одну небольшую задачу. Более подробно вопрос замены таск-раннеров npm-скриптами хорошо освещен в англоязычной статье Why I Left Gulp and Grunt for npm Scripts.

Итог

На рынке существует большая конкуренция инструментов для автоматизации рутинных задач (например, gulp и grunt), а также инструментов для автоматизации сборки проекта (Webpack, Broccoli, Medusa, Browserify и т.д.).

Если смотреть на таск-раннеры, то gulp по сравнению с grunt более прост, понятен и производителен: выигрывает за счет экономии на дисковых операциях. Но у grunt больше плагинов (например, есть плагин для тестирования). Из-за этого у него остается много поклонников.

Если же говорить только о сборке, то у gulp есть все преимущества перед grunt:

    Поточная архитектура для передачи файлов по цепочке, которую обеспечивает модуль Vynyl-FS.

    По умолчанию - асинхронное выполнение задач.

    Лаконичное API всего из 5 функций.

В то же время, для сборки Webpack является не менее интересным инструментом. В нем предусмотрена технология Live Reload, ускоряющая обновление браузера. Это огромный плюс: технология экономит время на нажатие кнопки обновления, которую разработчикам приходится нажимать постоянно. В gulp также есть Live Reload, но Webpack сложно сравнивать с gulp или grunt, так как он “заточен” только под билд и не “умеет” решать произвольные задачи.

Все эти решения прекрасно интегрируются с семейством продуктов от JetBrains, однако мы в WaveAccess предпочли именно grunt за широкие возможности и для верстальщиков, и для frontend-специалистов.

Если у Вас возникли вопросы и вам необходима разработка web-проекта, пишите нам на [email protected]

  • Frontend
  • Grunt
  • Gulp
  • Task runners

Приветствую. Если вы занимаетесь frontend разработкой, то могли заметить, что часто приходится выполнять одни и те же задачи. Было бы здорово все это автоматизировать и свести объем рутины к минимуму. В этом вам могут помочь таск-менеджеры и сборщики проектов, такие как Gulp и Grunt.

Gulp – это ответвление от проекта Grunt. От своего родителя он взял лучшие практики. Код инструкций пишется на JavaScript. Работает быстрее, чем Grunt в несколько раз.

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

  • Создание веб-сервера для отладки
  • Автоматическая перезагрузка страниц при внесении изменений (LiveReload)
  • Слежение за изменениями в файлах проекта
  • Использование препроцессоров HTML, CSS, JS
  • Объединение файлов и их минификация
  • Автоматическое создание вендорных префиксов для браузеров (Autoprefixer)
  • Автоматизация управления файлами и директориями
  • Запуск и контроль внешних команд операционной системы
  • Запуск и контроль приложений
  • Оптимизация изображений (сжатие, изменение размеров и т.д.)
  • Выгрузка проекта на внешний сервер с помощью FTP, SFTP, Git и т.д.
  • Подключение и использование дополнительных плагинов (сегодня их уже 3570 штук; решение можно
  • найти практически для всех повседневных рутинных задач и не только)
  • Автоматизация ручного труда

Установка

Для работы Gulp требуется Node.js. Скачать его можно на официальном сайте . Советую ставить LTS версию программной платформы. После инсталляции Node.js можно переходить к установке Gulp. Для этого откройте консоль операционной системы и выполните следующую команду:

Мы используем параметр -g , который позволяет установить Gulp глобально в операционной системе, без привязки к конкретному проекту.

Важно, чтобы в пути к директории установки не было русских символов. Из-за этого некоторые плагины gulp могут работать некорректно.

Окей, пришло время создать проект, в котором мы будем использовать Gulp. Перейдите в директорию проекта и выполните команду:

Это запустит скрипт, который задаст вам несколько вопросов о проекте. В результате будет сконфигурирован файл для npm package.json . Это манифест проекта. Он содержит список пакетов, которые используются в проекте и другую информацию. На этом этапе я внес следующие данные, адаптируйте под свой проект.

name: (bybtc-landing) version: (1.0.0) description: Landing Page for byBTC entry point: (index.js) test command: git repository: https://github.com/Neuropassenger/bybtc-landing.git keywords: landing

Если какой-то вопрос хотите пропустить, то просто нажимайте Enter. Будет использовано значение по умолчанию. Теперь можно установить Gulp для нашего проекта. Выполните команду:

npm i --save-dev gulp

Gulp будет установлен в директорию проекта, а параметр –save-dev добавит его в зависимости package.json. Это позволит другому разработчику, открывшему ваш проект, быстро развернуть его на своей машине (с помощью команды npm i ).

Если все прошло хорошо, то в папке проекта должен появиться каталог node_modules . Он содержит установленный пакет gulp и все зависимости, необходимые для его работы.

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

Создаем две папки в корне проекта:

  • /src/ – исходный код проекта во время разработки, здесь вы будете редактировать файлы
  • /dist/ – файлы и папки проекта после сборки, готовый продукт

Каталог /dist/ будет заполняться автоматически при сборке проекта. Займемся пока что /src/ . Создайте внутри следующие папки:

  • /css/ – для каскадных таблиц стилей
  • /js/ – для JavaScript-сценариев
  • /img/ – для изображений
  • /fonts/ – для шрифтов
  • /sass/ – для файлов препроцессора SASS (если используете SASS)
  • /libs/ – для сторонних библиотек

Если все готово, то пора перейти к созданию файла gulpfile.js в корне проекта, который поможет настроить Gulp. Именно здесь вы можете создать инструкции Gulp, которые помогут автоматизировать часть рутинных задач.

Инструкции Gulp

Любая инструкция создается в gulpfile.js с помощью функции gulp.task() . Первый параметр – это название инструкции. Затем идет массив из названий инструкций, которые нужно выполнить до запуска определяемой инструкции. Последний параметр – это функция, тело которой определяет то, что делает данная инструкция.

gulp.task("название_инструкции", ["инструкция_выполняющаяся_перед_текущей", "еще_одна_инструкция"], function() { // Какие-то действия });

Для вызова инструкции необходимо использовать в консоли следующую команду:

gulp название_команды

Компиляция SASS в CSS

Начнем с компиляции SASS в CSS. Установим пакет gulp-sass:

npm i --save-dev gulp-sass

Сначала необходимо подключить используемые пакеты в gulpfile.js . Сделаем это:

var gulp = require("gulp"), sass = require("gulp-sass");

Теперь создадим инструкцию, которая будет выполнять компиляцию SASS в CSS:

gulp.task("sass", function() { return gulp.src("src/sass/**/*.sass") .pipe(sass()) .pipe(gulp.dest("src/css")); });

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

  • src/sass/main.sass – выбор файла main.sass
  • src/sass/*.sass – выбор всех файлов с расширением sass
  • src/sass/**/*.sass – выбор всех файлов с расширением sass во всех вложенных папках в папке sass
  • !src/sass/main.sass – исключение файла main.sass
  • [‘!src/sass/main.sass’, ‘src/sass/second.sass’] – исключение массива файлов main.sass и second.sass
  • src/sass/**/*.+(scss|sass) – выбрать все файлы scss и sass во всех вложенных папках в sass

Теперь создаем в папке /src/sass/ файл main.sass и определим в нем немного стилей:

body color: red font-size: 20px

Сохраняем файл. Теперь мы можем проверить, как работает компиляция. В консоли выполняем команду:

Проверяем каталог /src/css/ . В нем должен находится только что скомпилированный CSS файл. Видите? Отлично! Двигаемся дальше.

Автообновление страниц (LiveReload)

Перейдем к автоматизации обновления страниц при их изменении, т.е. настроим LiveReload . Это одна из самых популярных задач, стоящих перед . Нам понадобится пакет npm Browsersync для автоматического обновления браузера. Установим его:

npm i --save-dev browser-sync

Подключим browser-sync пакет в начале gulpfile.js , как мы это делали ранее с пакетами gulp и gulp-sass :

browserSync = require("browser-sync");

Создадим инструкцию для запуска Browsersync:

gulp.task("browser-sync", function() { browserSync({ server: { baseDir: "src" } }); });

Все, что мы сделали – это вызвали запуск Browsersync и указали директорию проекта с исходными файлами. Есть и другие настройки для Browsersync . Можете узнать о них в документации.

Добавим еще один pipe к инструкции sass , с помощью которого будет происходить обновление стилей при компиляции CSS файлов. Указываем параметр stream: true . Это позволит обновлять стили потоково , без полной перезагрузки страницы.

Pipe(browserSync.reload({ stream: true; }))

Затем создадим инструкцию, которая будет следить за изменениями в файлах и перезагружать страницу при необходимости.

gulp.task("watch", ["browser-sync"], function() { gulp.watch("src/sass/**/*.sass", ["sass"]); gulp.watch("src/js/**/*.js", browserSync.reload); gulp.watch("src/**/*.html", browserSync.reload); });

Поясню. Перед запуском выполняется инструкция browser-sync , т.е. стартует веб-сервер для отладки проекта. После этого выполняется сама инструкция watch . Для слежения за изменениями в файлах используем gulp.watch() .

Внутри анонимной функции мы выполняем 3 раза gulp.watch с двумя параметрами. Первый параметр – файлы, за которыми нужно следить, второй – действия, которые нужно выполнить при изменении файлов, т.е. выполнить инструкцию sass или обновить страницу.

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

Минификация и объединение файлов

Почти в любом проекте приходится использовать сторонние библиотеки. Их количество может составлять от 5 и до бесконечности. Соответственно, все они должны быть включены в готовый продукт. Все это дело было бы неплохо оптимизировать, а именно:

  • минифицировать (сжать) используемые библиотеки
  • уменьшить количество запросов к серверу, объединив библиотеки в единый файл

Добавим в исходные файлы проекта несколько библиотек. Для этого я использую Bower , пакет для NPM . Установим Bower:

Создаем файл конфигурации .bowerrc в корне проекта для Bower, где укажем ему, куда сохранять библиотеки:

{ "directory": "src/libs/" }

Установим, для примера, библиотеку jQuery и слайдер slick :

bower i jquery slick-carousel

Теперь можем заняться конкатенацией и сжатием библиотек. Для этого будем использовать пакеты gulp-concat и gulp-uglifyjs касательно JavaScript-файлов. Установим их:

npm i --save-dev gulp-concat gulp-uglifyjs

Касательно CSS – пакет gulp-cssnano . Устанавливаем:

npm i --save-dev gulp-cssnano

Минифицированные файлы обычно имеют суффикс .min . Добавить его нам поможет пакет gulp-rename . Устанавливаем:

npm i --save-dev gulp-rename

Начнем с подключения установленных плагинов в gulpfile.js :

concat = require("gulp-concat"), uglifyJs = require("gulp-uglifyjs"), cssNano = require("gulp-cssnano"), rename = require("gulp-rename");

JavaScript

Создадим инструкцию, которая позволит нам сжимать и объединять JavaScript-файлы:

gulp.task("min-js", function() { return gulp.src([ "src/libs/jquery/dist/jquery.min.js", "src/libs/slick-carousel/dist/slick.min.js" ]) .pipe(concat("libs.min.js")) .pipe(uglifyJs()) .pipe(gulp.dest("src/js")); });

Внутри анонимной функции инструкции min-js мы сначала указываем пути на JavaScript-файлы библиотек в виде массива. Затем с помощью concat объединяем библиотеки в единый файл libs.min.js uglifyJs . И, наконец, сохраняем результат в папку /src/js/ .

Инструкцию можно проверить с помощью команды в консоли:

В папке /src/js/ появится файл libs.min.js , в котором объединены и сжаты используемые в проекте JavaScript-файлы библиотек.

CSS

Создадим в каталоге /src/css/ файл libs.sass . Будем в него импортировать CSS-файлы библиотек. Для примера с помощью Bower я скачал библиотеку Bootstrap :

bower i bootstrap

Откроем файл libs.sass и импортируем в него CSS-файл Bootstrap:

@import "src/libs/bootstrap/dist/css/bootstrap"

Таким образом, мы соберем все CSS-файлы библиотек в одном месте, а именно в файле libs.sass с помощью импорта. Теперь создадим инструкцию для сжатия:

gulp.task("min-css", ["sass"] , function() { return gulp.src("src/css/libs.css") .pipe(cssNano()) .pipe(rename({ suffix: ".min" })) .pipe(gulp.dest("src/css")); });

Перед сжатием мы компилируем CSS из SASS с помощью инструкции sass , которую мы указали в массиве после имени инструкции min-css .

В первой строке мы берем конкретный файл, libs.css . Далее сжимаем его с помощью cssNano . Затем с помощью rename добавляем суффикс .min . Результат сохраняем в папке /src/css/ .

Проверяем инструкцию:

Если вы все сделали правильно, то в папке /src/css/ должно появиться два файла. libs.css и libs.min.css . Сравните их размеры.

Автоматическое добавление вендорных префиксов (Autoprefixer)

При использовании свежих возможностей CSS необходимо расставлять вендорные префиксы для правильной работы стилей. Делать такие вещи вручную – неблагодарное занятие. Поэтому заставим Gulp это сделать за нас.

Для начала установим gulp-autoprefixer :

npm i --save-dev gulp-autoprefixer

Подключим установленный пакет в gulpfile.js :

autoprefixer = require("gulp-autoprefixer");

Окей, теперь мы можем использовать autoprefixer в инструкции sass . Сделаем это после вызова .pipe(sass()) , т.к. вендорные префиксы нужно расставить после того, как SASS будет преобразован в CSS. Добавим новый pipe :

Pipe(autoprefixer([ "last 10 versions" ], { cascade: true }))

Первым параметром autoprefixer мы передаем массив, в котором указываем, что хотим включить поддержку последних 10 версий браузеров. Второй параметр – это настройки, где мы указываем, что хотим видеть красивый код на выходе, т.е. включаем каскадность.

Проверяем, добавляя в main.sass новое свойство flex . Запускаем инструкцию sass :

В main.css должны появиться вендорные префиксы. Очень просто, все работает в автоматическом режиме. Замечательно!

Финальная сборка проекта

Последнее, чего хотелось бы коснуться в этом гайде для новичков по Gulp – это финальная сборка проекта. Для этого нам понадобится папка /dist/ , которую мы создали в самом начале. Перед каждой сборкой ее необходимо очищать. Для этого будем использовать пакет NPM del . Установим его:

npm i --save-dev del

Подключим пакет del в gulpfile.js :

del = require("del");

Создадим инструкцию clean для очистки каталога / dist/ перед сборкой:

gulp.task("clean", function() { return del.sync("dist"); });

Теперь можно заняться непосредственно сборкой проекта. Создадим инструкцию build :

gulp.task("build", ["clean", "min-css", "min-js"], function() { var buildCss = gulp.src([ "src/css/libs.min.css", "src/css/main.css" ]) .pipe(gulp.dest("dist/css")); var buildFonts = gulp.src("src/fonts/**/*") .pipe(gulp.dest("dist/fonts")); var buildJs = gulp.src("src/js/**/*") .pipe(gulp.dest("dist/js")); var buildHtml = gulp.src("src/*.html") .pipe(gulp.dest("dist")); });

Перед вызовом инструкции build мы очищаем папку /dist/ на тот случай, если сборка уже проводилась до этого. Затем сжимаем и объединяем JavaScript и CSS файлы с помощью инструкций min-js и min-css соответственно . Попутно компилируем SASS в CSS, т.к. перед выполнением инструкции min-css выполняется инструкция sass .

Внутри тела инструкции мы копируем подготовленные файлы проекта в каталог с готовым продуктом /dist/ . Проверяем работу инструкции:

Все отлично работает! В папке /dist/ теперь находится готовый продукт после сборки, который можно выгружать на рабочий сервер.

Заключение

На этом закончу гайд для новичков по сборке проектов в Gulp. Как видите, все довольно просто. Со временем опубликую еще несколько постов, касающихся Gulp и его плагинов, как только сам хорошенько в них разберусь. А пока пользуйтесь и автоматизируйте свои рутинные задачи во frontend разработке согласно приведенной инструкции. Если появятся вопросы – задавайте в комментариях к посту.

{ "name": "bybtc-landing", "version": "1.0.0", "description": "Landing Page for byBTC", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+https://github.com/Neuropassenger/bybtc-landing.git" }, "keywords": [ "landing" ], "author": "Oleg Sokolov", "license": "ISC", "bugs": { "url": "https://github.com/Neuropassenger/bybtc-landing/issues" }, "homepage": "https://github.com/Neuropassenger/bybtc-landing#readme", "devDependencies": { "browser-sync": "^2.18.13", "del": "^3.0.0", "gulp": "^3.9.1", "gulp-autoprefixer": "^4.0.0", "gulp-concat": "^2.6.1", "gulp-cssnano": "^2.1.2", "gulp-rename": "^1.2.2", "gulp-sass": "^3.1.0", "gulp-uglifyjs": "^0.6.2" } }

var gulp = require("gulp"), sass = require("gulp-sass"), browserSync = require("browser-sync"), concat = require("gulp-concat"), uglifyJs = require("gulp-uglifyjs"), cssNano = require("gulp-cssnano"), rename = require("gulp-rename"), autoprefixer = require("gulp-autoprefixer"), del = require("del"); gulp.task("sass", function() { return gulp.src("src/sass/**/*.sass") .pipe(sass()) .pipe(autoprefixer([ "last 10 versions" ], { cascade: true })) .pipe(gulp.dest("src/css")) .pipe(browserSync.reload({ stream: true })); }); gulp.task("min-css", ["sass"] , function() { return gulp.src("src/css/libs.css") .pipe(cssNano()) .pipe(rename({ suffix: ".min" })) .pipe(gulp.dest("src/css")); }); gulp.task("min-js", function() { return gulp.src([ "src/libs/jquery/dist/jquery.min.js", "src/libs/slick-carousel/dist/slick.min.js" ]) .pipe(concat("libs.min.js")) .pipe(uglifyJs()) .pipe(gulp.dest("src/js")); }); gulp.task("browser-sync", function() { browserSync({ server: { baseDir: "src" } }); }); gulp.task("watch", ["browser-sync"], function() { gulp.watch("src/sass/**/*.sass", ["sass"]); gulp.watch("src/js/**/*.js", browserSync.reload); gulp.watch("src/**/*.html", browserSync.reload); }); gulp.task("clean", function() { return del.sync("dist"); }); gulp.task("build", ["clean", "min-css", "min-js"], function() { var buildCss = gulp.src([ "src/css/libs.min.css", "src/css/main.css" ]) .pipe(gulp.dest("dist/css")); var buildFonts = gulp.src("src/fonts/**/*") .pipe(gulp.dest("dist/fonts")); var buildJs = gulp.src("src/js/**/*") .pipe(gulp.dest("dist/js")); var buildHtml = gulp.src("src/*.html") .pipe(gulp.dest("dist")); });

Похожие публикации