Приятная сборка frontend проекта. И напоследок маленькая милость
В последнее время 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). Вы можете использовать эту задачу для запуска других необходимых вам задач при изменении файлов.
сентябрь 24 , 2016
Будут рассмотрены такие вопросы: работа со стилями sass с использованием sourcemaps, склеивание и сжатие js-файлов, сборка requirejs с помощью rjs, препроцессинг html, очистка и копирование файлов, оптимизация изображений, поднятие локального веб-сервера и режим наблюдения - watch-таски.
Добро пожаловать в статью, будет много интересного!
P.S. Материала много, поэтому статья будет разбита на 3 части: основы сборки и организация проекта, написание тестового приложения на Backbone + Require.js и собственно сборка с помощью gulp.
Зачем нужна сборка фронтенда.
Один из самых важных принципов в разработке - это модульность. Разбиение кода проекта на множество небольших, в идеале слабосвязанных между собой кусочков-модулей. Это касается далеко не только javascript-кода. Это относится и к стилям, и html-шаблонам, к различным библиотекам.
Примерно так может выглядеть структура простого приложения, написанного на Backbone + Require.
И это небольшой тестовый проект, в реальном приложении файлов может быть сотни и тысячи. Заставлять браузер пользователя делать сотни http-запросов по меньшей мере негуманно. Мы должны обеспечить максимально быструю загрузку написанного нами сервиса. Поэтому одна из самых важных задач инструментов сборки - это минификация, уменьшение количества используемых на проекте файлов, склеивание их в бандлы. На выходе мы должны иметь более краткую структуру, например, вот такую:
Разница хорошо заметна: вместо десятков файлов мы имеем один index.html, один css-файл, оптимизированные и сжатые изображения в отдельной папке, хотя на скриншоте этого и не видно:-)
А также самое интересное: в папке js мы получили всего 3 сжатых файла.
P.S. Почему три, а не один, расскажу позже.
Замечу, что это реальная структура тестового приложения, которое мы вскоре напишем.
Я описал лишь одну причину использования инструментов сборки, но она уже достаточна, чтобы начать использовать gulp, grunt, webpack или что-то подобное в своих проектах. Причем не имеет значения, пишем ли мы громадный сервис, небольшое SPA (как в нашей статье) или landing page. Принципы сборки одинаковы для всех проектов и различаются лишь разнообразием задач и подходов к их решению. В нашем примере мы создадим такую структуру, которая может сколь угодно расшириться в дальнейшем, но на выходе всегда будет аккуратная стопка файлов, готовая к выливке на ваш продакшен - боевой сайт.
Как правильно организовать проект.
Принцип такой: есть раздел с девелоперскими файлами, есть с собранными и все остальное, что это добро обслуживает. Создадим в корне проекта 2 папки: src и build. В src и только в src мы будем работать, создавать новые файлы, редактировать их и вообще развлекаться. На скриншоте выше, там, где пара десятков файлов, Вы видели именно содержимое папки src нашего тестового проекта. А чуть ниже несколько аккуратных файлов из папки build. Она формируется только автоматически, инструментами сборки, ничего самим там править не нужно. Все равно при каждой сборке ее содержимое затирается новыми файлами (а в режиме development папки build вообще нет - удаляется, дабы не мозолить глаза)
Кроме src и build в корне будут лежать файлы package.json, gulpfile.js, папка node_modules и опционально, .gitignore (если Вы работает с гитом). У меня еще можно заметить папку logs - это порождение apache и давняя привычка держать логи проекта в его же папке, конечно, исключив ее из репозитория гита:-)
Вот так выглядит структура проекта целиком:
По содержимому build, думаю, вопросов нет, по src поясню подробнее:
- 1. html - index.html, корневой индексный файл проекта. Почему не сразу в корне src? Потому что он будет препроцесситься и создаваться gulp-ом. Каким образом, узнаем немного позже, когда вплотную займемся сборкой.
- 2. img - изображения, не сжатые, обычные
- 3. js - вся javascript-движуха проекта, модели и представления Backbone
- 4. lib - сторонние библиотеки, вроде backbone.js, require.js, lodash.js и прочих
- 5. scripts - js-скрипты, которые необходимы на боевом сайте, но не нужны в режиме разработки. Имеются в виду коды для аналитики, различных экспериментов и прочих маркетинговых штук.
- 6. styles - sass-файлы со стилями. В эту же папку будет складываться собранный css-файл (только для режима девелопмента)
- 7. tpl - html-шаблоны. Используются представлениями Backbone с помощью плагина require.js text
Внешний вид тестового приложения довольно неказистый.
Вы можете сказать, что подобная хрень делается парой строк html и css-кода без единого js-файла.
Но мы преследуем цель не нарисовать красивую картинку,
а создать надежную структуру проекта и рассмотреть как можно больше аспектов сборки.
Когда проект разрастется до сотни файлов, мы уже будем готовы к этой напасти и легко управимся с возросшими объемами.
Поэтому несмотря на малость и внешнюю убогость тестового приложения, мы узнаем принципы сборки для больших и сложных проектов.
Какие задачи сборки мы решим.
Напомню, что мы договорились о двух режимах сборки: development и production. Все наши задачи мы будем писать, помня об этих двух режимах. Не все операции нам нужны в процессе разработки, и не все в сборке для продакшена.
Вот список того, чем мы займемся после написания тестового приложения:
- 1. Очистка файлов и папок от результатов предыдущей сборки
- 2. Сборка css из sass-файлов, со сжатием и без
- 3. Подключение sourcemaps к стилям, заодно покажу на примере, зачем это нужно
- 4. Сборка js-бандла с помощью requirejs
- 5. Склеивание и сжатие отдельных js-файлов (аналитики)
- 6. Препроцессинг html
- 7. Оптимизация и сжатие изображений
- 8. Поднятие локального веб-сервера
- 9. Задачи наблюдения за файлами при работе в режиме девелопмента - watch-таски
- 10. Сбор отдельных задач в кучу - итоговые таски для production-сборки и development-работы
Итак, мы порассуждали, зачем вообще нужна сборка фронтенда, определились со структурой проекта, подробно разобрали, что мы хотим от сборки и в общих чертах поговорили про тестовое приложение. В следующей части статьи мы займемся написанием простенького Backbone-приложения в связке с Require.js. Если Вы не знакомы с Backbone и/или Require.js, то ничего страшного нет. Собственно Backbone-овского кода в приложении мало. Вы легко можете вместо него использовать любимую библиотеку или просто писать код на javascript/jquery и пропустить раздел настройки requirejs.
Хотите набрать побольше баллов в Google Page Speed? Не знаете что такое «сборка front-end»? Тогда вам сюда, будет интересно.
Что такое Node.JS?
Node.JS принято называть «северным JavaScript». Эта платформа позволяет писать программы, используя синтаксис JavaScript.
Есть реализации для Windows, Mac OS и Linux.
В комплект входит менеджер пакетов NPM , с помощью которого можно устанавливать пакеты.
Что такое Gulp?
Gulp — это пакет, написанный на Node.JS, который помогает веб-мастерам осуществлять сборку проектов на этапе верстки макетов.
Для установки Gulp необходимо воспользоваться командной строкой.
Npm install gulp
В конце данной статьи находится файл, который поможет собрать типовой проект.
В этом примере с помощью Gulp мы сделаем следующее:
- Автоматически оптимизируем изображения для веба;
- Собираем один минифицированный файл стилей из предпроцессоров (SASS, SCSS);
- Собираем один минифицированный файл со скриптами.
Как собирать front-end с помощью Gulp?
Чтобы понять, как все работает, разберем все по шагам.
Структуру можно посмотреть на скриншоте.
- Папка assets — для исходников изображений, стилей и скриптов;
- Папка public — результат сборки проекта будет находится именно в ней;
- gulpfile.js — файл, в котором описана логика работы сборщика;
- package.json — файл, в котором содержатся информация о программах и плагинах, использующихся для корректной работы Gulp.
package.json
Содержимое файла:
{ "name": "gulp_project", "version": "1.0.0", "description": "Example", "main": "gulpfile.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Dmitriy Ilichev", "license": "ISC", "devDependencies": { "gulp": "^3.9.0", "gulp-csso": "^1.0.0", "gulp-concat": "^2.6.0", "gulp-uglify": "^1.2.0", "gulp-imagemin": "^2.3.0", "gulp-sass": "^2.1.1" } }
Из этого файла понятно следующее:
- Название проекта gulp_project , версия и описание;
- Главный файлом является gulpfile.js ;
- Автор проекта, лицензия — все это не столь важно и попросту эти поля могут быть пустыми;
- Интересным пунктом является devDependencies . В нем описаны зависимости.
Файл можно отредактировать в обычном текстовом редакторе. Его также можно создать для нового проекта командой npm int .
Исходя из этого, Node.JS понимает, что для работы нам понадобятся:
- Gulp версии 3.9.0 и выше для сборки;
- Gulp-csso версии 1.0.0 и выше — плагин для минификации стилей (css);
- Gulp-concat версии 2.6.0 и выше — плагин для склейки нескольких файлов в один;
- Gulp-uglify версии 1.2.0 и выше — плагин для минификации javascript;
- Gulp-imagemin версии 2.3.0 и выше — плагин для оптимизации изображений;
- Gulp-sass версии 2.1.1 и выше — плагин для получения css из sass (scss).
Отлично! После этого нужно все это установить. Делается это из командной строки. Находясь в папке с проектом нужно выполнить команду:
Npm install
Вся необходимая информация будет взята из package.json .
После всего этого волшебства появится служебная папка node_modules .
gulpfile.js
Содержимое файла:
/* * * Определяем переменные * */ var gulp = require("gulp"), // Сообственно Gulp JS uglify = require("gulp-uglify"), // Минификация JS concat = require("gulp-concat"), // Склейка файлов imagemin = require("gulp-imagemin"), // Минификация изображений csso = require("gulp-csso"), // Минификация CSS sass = require("gulp-sass"); // Конверстация SASS (SCSS) в CSS /* * * Создаем задачи (таски) * */ // Задача "sass". Запускается командой "gulp sass" gulp.task("sass", function () { gulp.src("./assets/styles/style.scss") // файл, который обрабатываем.pipe(sass().on("error", sass.logError)) // конвертируем sass в css .pipe(csso()) // минифицируем css, полученный на предыдущем шаге.pipe(gulp.dest("./public/css/")); // результат пишем по указанному адресу }); // Задача "js". Запускается командой "gulp js" gulp.task("js", function() { gulp.src([ "./assets/javascripts/jquery-2.1.4.min.js", "./assets/javascripts/bootstrap.min.js", "./assets/javascripts/script.js" ]) // файлы, которые обрабатываем.pipe(concat("min.js")) // склеиваем все JS .pipe(uglify()) // получившуюся "портянку" минифицируем.pipe(gulp.dest("./public/js/")) // результат пишем по указанному адресу }); // Задача "images". Запускается командой "gulp images" gulp.task("images", function() { gulp.src(".assets/images/**/*") // берем любые файлы в папке и ее подпапках.pipe(imagemin()) // оптимизируем изображения для веба.pipe(gulp.dest("./public/images/")) // результат пишем по указанному адресу }); // Задача "watch". Запускается командой "gulp watch" // Она следит за изменениями файлов и автоматически запускает другие задачи gulp.task("watch", function () { // При изменение файлов *.scss в папке "styles" и подпапках запускаем задачу sass gulp.watch("./assets/styles/**/*.scss", ["sass"]); // При изменение файлов *.js папке "javascripts" и подпапках запускаем задачу js gulp.watch("./assets/javascripts/**/*.js", ["js"]); // При изменение любых файлов в папке "images" и подпапках запускаем задачу images gulp.watch("./assets/images/**/*", ["images"]); });
Главная фишка — в задаче watch . Запустив ее один раз, можно спокойно работать с источниками, и проект будет автоматически собираться при каждом сохранении редактируемых файлов.
На выходе получим готовый к публикации в интернете шаблон.
Задачи можно запускать отдельно. В итоге, в архиве в конце статьи вас ждет следующее:
! Обратите внимание на то, что распаковав у себя этот архив, прежде всего необходимо будет выполнить команду npm install . Папка эта содержит довольно большое количество файлов, и каждый раз копировать/вставлять их — пустая трата времени.
В заключении
Есть огромное множество других полезных плагинов. Например, прекрасный шаблонизатор Jade, который в разы ускоряет написание html кода, кому-то может понадобится LESS и так далее.
Представленный пример — всего лишь платформа и шаблон, с которого быстро и без особых знаний можно начать пользоваться всеми этими прекрасными фишками.
Таск-раннеры и системы сборки сильно ускоряют работу, автоматизируя компиляцию, тестирование и другие рутинные задачи. Как и в любой другой области, на этом рынке существует сильная конкуренция. До 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
В этой статье рассмотрим пример Gulp окружения, которое можно использовать для комфортной фронтенд разработки веб-проекта. Данный пример по умолчанию сконфигурирован для создания сайтов и веб-приложений, в основу которых положен фреймворк Bootstrap 4.
Проект, рассматриваемый в рамках этой статьи расположен на Github по адресу: https://github.com/itchief/gulp-project-bootstrap-4
Видео к этой статье:
Инструкция по установке Gulp окружения
Для создания окружения необходимо иметь следующие установленные программы:
- "Node.js" (загрузить установщик "Node.js" для своей операционной системы можно c этой страницы ; для проекта требуется версия программы не ниже 10 );
- "Gulp" (установить Gulp можно посредством выполнения в консоли следующей команды: npm install -g gulp-cli).
Следующий этап – это установка npm пакетов и их зависимостей. Для этого в консоли (должны находиться в корневой директории проекта) необходимо выполнить команду:
Npm install
Данная команда установит все пакеты, которые нужны как для работы самого окружения, так и для фронтенда. Выполняет npm эти действия в соответствии с инструкциями, написанными в файле "package.json".
При использовании первой версии проекта (1.0.0), в которой используется менеджер пакетов Bower, необходимо выполнить ещё команду:
Bower install
Данная программа установит фронтенд пакеты, указанные в файле "bower.json".
Как использовать Gulp окружение?
Открыть командную строку (путь должен указывать на корневую папку проекта) и ввести gulp (обычный режим):
После ввода этой команды запустится задача по умолчанию, т.е. "default". Эта задача в свою очередь запустит серию других задач: "build", "webserver" и "watch".
Задача "build" выполнит сборку проекта для продакшена (т.е. она запустит "clean:build", "html:build", "css:build", "js:build", "fonts:build" и "image:build"). Эти задачи поместят в папку "assets/build" результирующие файлы проекта.
Задача "webserver" предназначена для запуска локального веб-сервера с «живой перезагрузкой» страниц в браузере. С помощью него можно очень просто посмотреть проект и выполнить его тестирование.
Задача "watch" используется для отслеживания изменения исходных файлов в папке "assets/src" и выполнение если это призошло различных задач. Другими словами, она позволяет автоматически запускать необходимые задачи и поддерживать результирующие файлы (содержимое папки "assets/build") в актуальном состоянии.
Кроме этого можно выполнять выборочную (самостоятельную) сборку той или иной части проекта.
Например, для сборки только CSS части сайта достаточно ввести команду:
Gulp css:build
Список других задач:
Gulp clean:build // для очистки каталога "assets/build" gulp html:build // для сборки HTML файлов gulp js:build // для сборки JS файлов gulp fonts:build // для сборки шрифтов gulp image:build // для сборки изображения
Описание Gulp окружения
В этом разделе разберём:
- основные инструменты и файловую структуру Gulp окружения;
- как осуществляется подключение исходников Bootstrap к проекту и их настройка;
- как самостоятельно (с нуля) выполнить инициализацию Gulp проекта и установку зависимостей (без использования готового package.json)
- как с нуля выполнить инициализацию Bower и установку фронтенд пакетов (без использования готового "bower.json")*;
- содержимое файла сборщика проекта Gulp (gulpfile.js)
* Менеджер пакетов Bower не используется в проекте, начиная с версии 2.0.0.
Список инструментов
Окружение, предназначенное для разработки фронтенд проекта (сайта), построено на базе следующих инструментов:
- Node.js (среды, в которой будет выполняться окружение);
- npm (пакетного менеджера, входящего в Node.js; будет использоваться для загрузки Gulp, плагинов и фронтенд пакетов);
- jQuery, Popover, Bootstrap (пакеты, которые будут использоваться для сборки css и js частей сайта);
- Gulp и его плагины (будут использоваться для сборки проекта и выполнения других веб задач).
В первых версиях проекта дополнительно ещё использовался пакетный менеджер Bower. Он применялся за загрузки библиотек jQuery, Popover и Bootstrap. В версиях проекта, начиная с 2.0.0, загрузка данных библиотек выполняется посредством npm.
Файловая структура Gulp проекта
Файловую структуру проекта можно организовать по-разному. Это может зависеть как от предпочтений конкретного разработчика, так и от проекта, для которого она создаётся.
В данной статье будем придерживаться следующей структуры:
В корне проекта расположена папка "assets" и файлы "gulpfile.js", "package.json". Файл "gulpfile.js" будет содержать задачи для сборщика проекта Gulp.
В первой версии проекта также использовались файлы ".bowerrc" и "bower.json". Файл "bower.json" - это конфигурационный файл менеджера Bower, на основании которого определялись необходимые для загрузки фронтенд пакеты. В данном проекте он использовался для загрузки Bootstrap, jQuery и Popper.
В папке "assets" находятся две папки: "src" (для исходных файлов) и "build" (для готовых файлов; в эту папку их будет помещать сборщик Gulp). В папке "src" расположены каталоги "fonts" (для шрифтов), "img" (для исходных изображений), "js" (для js-файлов), "style" (для стилей) и "template" (для HTML фрагментов) и файл "index.html".
В первой версии проекта в папке "src" ещё находилась директория "bower_components". Она предназначалась для компонентов, загрузка которых выполнялась с помощью Bower. В текущей версии её нет.
В каталоге "js" распологаются два файла: "main.js" и "my.js". Файл "my.js" используется для написания своих скриптов, а "main.js" – для определения списка файлов, содержимое которых необходимо будет включить в итоговый js-файл. Под итоговым понимается файл, который должен получиться на выходе (в каталоге "build").
Директория "style" отведена под стили. В данной директории находятся три файла: "main.scss" (содержит список файлов, содержимое которых необходимо включить в итоговый файл стилей), "my.scss" (используется для написания своих стилей) и "variables.scss" (содержит SCSS переменные, с помощью которых будем изменять стили Bootstrap 4, а также использовать его для создания своих переменных).
Файл "index.html" - это главная страница создаваемого проекта. Кроме "index.html" в данную директорию можно поместить и другие html страницы.
Директория "template" предназначена для помещения в неё фрагментов HTML страниц. Например, в данной директории можно создать файлы "head.html" и "footer.html", и импортировать их содержимое (используя синтаксис //= путь_к_файлу) сразу в несколько страниц. Это позволит более просто создавать и редактировать html страницы, т.к. отдельные части страниц уже будут находиться в отдельных файлах.
Подключение исходников Bootstrap 4 к проекту и их настройка
Существуют разные способы подключения фреймворка Bootstrap 4 к проекту, а также варианты работы с ним.
Наиболее гибкий вариант заключается в использовании исходных кодов. В этом случае можно не только очень просто изменять дефолтные стили Bootstrap , но и подключать к проекту только те классы и компоненты, которые в нём будут использоваться .
Исходные коды CSS стилей Bootstrap 4 написаны на языке SCSS и представлены посредством большого количества небольших файлов.
Список SCSS файлов (расположены в каталоге "node_modules/bootstrap/scss/"): "functions.scss", "variables.scss", "mixins.scss", "variables.scss", "print.scss", "reboot.scss", "type.scss", "images.scss", "code.scss", "grid.scss", "tables.scss", "forms.scss", "buttons.scss", "transitions.scss", "dropdown.scss" и др.
Каждой такой файл выполняет либо определённую служебную задачу, либо отвечает за стилизацию какой-то определённой функции фреймворка или компонента. Файлы SCSS имеют краткие и понятные имена. Используя только их можно достаточно точно понять назначение каждого из них.
Настройка или изменение дефолтных стилей Bootstrap 4 осуществляется посредством переопределения значений переменных SCSS . Все SCSS переменные для удобства собраны в одном месте (в файле "variables.scss"). Но, переопределять их значения желательно, конечно же, не в этом файле, а в своём (например, имеющим такое же имя "variables.scss", но находящемся в "assets/style/variables.scss").
Например, изменение цвета тем success и danger , осуществляется посредством изменения значений переменных $green и $red:
// Переопределение дефолтных значений переменных Bootstrap 4 $red: #cc2eaa; $green: #2ecc71;
Обратите внимание , что после копирования переменных Bootstrap 4 в свой файл CSS ("assets/style/variables.scss"), у них необходимо убрать метку!default .
Метка!default предназначена для установления SCSS переменной значения по умолчанию. Если же у SCSS переменной уже есть значение, то новое значение, если оно указано с ключом!default , установлено не будет.
Указать какие исходные SCSS файлы Bootstrap 4 должны участвовать при компиляции в CSS, а какие нет, выполняется посредством SCSS файла "assets/style/main.scss". Другими словами именно содержимое этого файла и будем определять тот набор стилей, который после компиляции будет подключен к веб-странице.
Кроме этого, к этому файлу также подключёны файлы "assets/style/variables.scss" (для переопределения переменных Bootstrap) и "assets/style/my.scss" (для создания своих стилей).
Содержимое файла "main.scss" (пример):
// Переопределение дефолтных значений переменных Bootstrap 4 и определение своих @import "variables"; // Подключение нужных SCSS исходников Bootstrap 4 @import "../../../node_modules/bootstrap/scss/_functions"; @import "../../../node_modules/bootstrap/scss/_variables"; @import "../../../node_modules/bootstrap/scss/_mixins"; @import "../../../node_modules/bootstrap/scss/_root"; @import "../../../node_modules/bootstrap/scss/_reboot"; @import "../../../node_modules/bootstrap/scss/_type"; @import "../../../node_modules/bootstrap/scss/_images"; @import "../../../node_modules/bootstrap/scss/_code"; @import "../../../node_modules/bootstrap/scss/_grid"; @import "../../../node_modules/bootstrap/scss/_tables"; @import "../../../node_modules/bootstrap/scss/_forms"; @import "../../../node_modules/bootstrap/scss/_buttons"; @import "../../../node_modules/bootstrap/scss/_transitions"; @import "../../../node_modules/bootstrap/scss/_dropdown"; @import "../../../node_modules/bootstrap/scss/_button-group"; @import "../../../node_modules/bootstrap/scss/_input-group"; @import "../../../node_modules/bootstrap/scss/_custom-forms"; @import "../../../node_modules/bootstrap/scss/_nav"; @import "../../../node_modules/bootstrap/scss/_navbar"; @import "../../../node_modules/bootstrap/scss/_card"; @import "../../../node_modules/bootstrap/scss/_breadcrumb"; @import "../../../node_modules/bootstrap/scss/_pagination"; @import "../../../node_modules/bootstrap/scss/_badge"; @import "../../../node_modules/bootstrap/scss/_jumbotron"; @import "../../../node_modules/bootstrap/scss/_alert"; @import "../../../node_modules/bootstrap/scss/_progress"; @import "../../../node_modules/bootstrap/scss/_media"; @import "../../../node_modules/bootstrap/scss/_list-group"; @import "../../../node_modules/bootstrap/scss/_close"; @import "../../../node_modules/bootstrap/scss/_toasts"; @import "../../../node_modules/bootstrap/scss/_modal"; @import "../../../node_modules/bootstrap/scss/_tooltip"; @import "../../../node_modules/bootstrap/scss/_popover"; @import "../../../node_modules/bootstrap/scss/_carousel"; @import "../../../node_modules/bootstrap/scss/_spinners"; @import "../../../node_modules/bootstrap/scss/_utilities"; @import "../../../node_modules/bootstrap/scss/_print"; // Подключение своих SCSS файлов @import "my";
Кроме этого, для работы некоторых компонентов Bootstrap 4 нужен ещё JavaScript код.
Список js-файлов Bootstrap 4 (находятся в каталоге "node_modules/bootstrap/js/dist/"): "util.js", "alert.js", "button.js", "carousel.js", "collapse.js", "dropdown.js", "modal.js", "tooltip.js", "popover.js", "scrollspy.js", "tab.js" и "toast.js".
Определение какие js-файлы фреймворка Bootstrap 4 необходимо включить в итоговый js-файл проекта, а какие нет, выполняется посредством "main.js".
Импортирование нужных файлов в результирующий build/main.js осуществляется посредством следующей конструкции:
//= путь_к_файлу
Выполняет это действие будет Gulp плагин "gulp-rigger". Как его установить и подключить будет описано ниже.
В данный файл можно также импортировать jQuery, Popper (необходим для работы компонентов Dropdown, Tooltip и Popover) и при необходимости свои js-файлы.
Содержимое файла "main.js" (пример):
// Импортируем jQuery //= ../../../node_modules/jquery/dist/jquery.js // Импортируем Popper //= ../../../node_modules/popper.js/dist/umd/popper.js // Импортируем необходимые js-файлы Bootstrap 4 //= ../../../node_modules/bootstrap/js/dist/util.js //= ../../../node_modules/bootstrap/js/dist/alert.js //= ../../../node_modules/bootstrap/js/dist/button.js //= ../../../node_modules/bootstrap/js/dist/carousel.js //= ../../../node_modules/bootstrap/js/dist/collapse.js //= ../../../node_modules/bootstrap/js/dist/dropdown.js //= ../../../node_modules/bootstrap/js/dist/modal.js //= ../../../node_modules/bootstrap/js/dist/tooltip.js //= ../../../node_modules/bootstrap/js/dist/popover.js //= ../../../node_modules/bootstrap/js/dist/scrollspy.js //= ../../../node_modules/bootstrap/js/dist/tab.js //= ../../../node_modules/bootstrap/js/dist/toast.js // Импортируем другие js-файлы //= my.js
Как с нуля выполнить инициализацию Gulp проекта и установку зависимостей?
Начинается разработка проекта обычно с создания файла "package.json" (манифеста).
Файл "package.json" будет содержать общую информацию о проекте (название, версию, описание, имя автора и др.), а также данные о пакетах, от которых этот проект зависит.
Для создания манифеста, необходимо перейти в корневую папку проекта и ввести команду:
Npm init
После ввода команды необходимо ответить на следующие вопросы:
- имя проекта (name) – "bootstrap-4";
- номер версии (version) – "2.0.0";
- описание (description) – "Start project with use Bootstrap 4";
- автор (author) – "сайт";
- git репозиторий (git repository) - "";
- точка входа (entry point), тестовая команда (test command), лицензия (license), ключевые слова (keywords) – значения по умолчанию.
На вопрос «Is this ok?» ответим "yes" или нажмём Enter .
В результате в корневой папке проекта появится файл "package.json".
Теперь установим пакеты, которые будем использовать в проекте с помощью следующей команды:
Npm install название_пакета --save-dev // установка пакета, при этом информация о нём, автоматически прописывается в секцию "devDependencies" файла "package.json" npm install название_пакета --save-prod // установка пакета, при этом информация о нём, автоматически прописывается в секцию "dependencies" файла "package.json"
Ключ "--save-dev" или "--save-prod" определяет в какую секцию файла "package.json" попадёт информация о нём.
Список пакетов, которые будут использоваться в проекте:
Npm install gulp --save-dev // установка gulp npm install browser-sync --save-dev // установка browser-sync npm install gulp-autoprefixer --save-dev // установка gulp-autoprefixer npm install gulp-cache --save-dev // установка gulp-cache npm install gulp-clean-css --save-dev // установка gulp-clean-css npm install gulp-rimraf --save-dev // установка gulp-clean-css npm install gulp-imagemin --save-dev // установка gulp-imagemin npm install gulp-plumber --save-dev // установка gulp-plumber npm install gulp-rigger --save-dev // установка gulp-rigger npm install gulp-sass --save-dev // установка gulp-sass npm install gulp-sourcemaps --save-dev // установка gulp-sourcemaps npm install gulp-uglify --save-dev // установка gulp-uglify npm install imagemin-jpeg-recompress --save-dev // установка imagemin-jpeg-recompress npm install imagemin-pngquant --save-dev // установка imagemin-pngquant npm install gulp-rename --save-dev // установка imagemin-pngquant npm install jquery --save-prod npm install popper.js --save-prod npm install bootstrap --save-prod
После установки всех зависимостей, файл package.json будет иметь следующее содержимое:
{ "name": "bootstrap-4", "version": "2.0..com/itchief/gulp-project-bootstrap-4.git" }, "dependencies": { "jquery": "^3.4.1", "popper.js": "^1.14.7", "bootstrap": "^4.3.1" }, "devDependencies": { "browser-sync": "^2.26.7", "gulp": "^4.0.2", "gulp-autoprefixer": "^6.1.0", "gulp-cache": "^1.1.2", "gulp-clean-css": "^4.2.0", "gulp-rimraf": "^0.2.2", "gulp-imagemin": "^6.0.0", "gulp-plumber": "^1.2.1", "gulp-rigger": "^0.5.8", "gulp-sass": "^4.0.2", "gulp-sourcemaps": "^2.6.5", "gulp-uglify": "^3.0.2", "imagemin-jpeg-recompress": "^6.0.0", "imagemin-pngquant": "^8.0.0", "gulp-rename": "^1.4.0" } }
Как с нуля выполнить инициализацию Bower и установку фронтенд пакетов?
Определим папку, в которую Bower будет загружать пакеты. Для этого создадим файл.bowerrc и введём в него следующее:
{ "directory" : "assets/src/bower_components/" }
Сохраним файл.bowerrc . Теперь все компоненты будут загружаться в каталог bower_components , находящийся в assets/src/ .
Выполним инициализацию Bower (создадим файл-манифест bower.json). Создание файла bower.json можно осуществить с помощью команды (в корневой папке проекта):
Bower init
Инициализация Bower
После этого необходимо ответить на следующие вопросы:
- имя проекта (name) – bootstrap-4;
- описание (description) – Start project on Bootstrap 4 - сайт;
- автор (author) – сайт;
- установить установленные компоненты как зависимости (set currently installed components as dependencies) – Y (Да);
- хотите вы отметить этот пакет как приватный, это предотвратит его случайную публикацию в реестре Bower (would you like to mark this package as private which prevents it from being accidentally published to the registry) – Y (Да);
- на остальные вопросы оставим ответы, предлагаемые программой по умолчанию;
В результате этих действий будет создан файл bower.json .
Загрузим Bootstrap 4 и пакеты от которых он зависит (Popper и jQuery) в наш проект с помощью Bower.
Для этого в консоли необходимо ввести следующую команду:
Bower install bootstrap#v4.0.0-beta --save
Ключ -save необходим для того, чтобы информацию о пакете записать в секцию dependencies файла bower.json .
В результате bower.json будет иметь следующее содержимое:
{ "name": "bootstrap-4", "description": "Start project on Bootstrap 4 - сайт", "authors": [ "сайт" ], "license": "ISC", "keywords": , "homepage": "", "ignore": [ "**/.*", "node_modules", "bower_components", "assets/src/bower_components/", "test", "tests" ], "dependencies": { "jquery": "^3.2.1", "bootstrap": "^v4.0.0-beta" } }
Если вы не хотите инициализировать Bower (bower.json) с помощью команды bower init и устанавливать пакеты вручную, то можете просто создать файл bower.json (например, с помощью файлового менеджера) и вставить в него вышепредставленное текстовое содержимое. Для установки зависимостей в проект достаточно будет ввести следующую команду:
Bower install
Описание файла сборщика проекта Gulp (gulpfile.js)
Все действия, выполненные до этого, были подготовительными. Весь функционал, который будет выполнять создаваемое окружение, будет определяться файлом "gulpfile.js".
Файл "gulpfile.js" представляет собой список задач.
Основные задачи которые будут выполнять этот файл:
- сбор нескольких файлов стилей в один, компиляция полученного SCSS в CSS, добавление автопрефиксов, минимизация CSS и создание source map;
- импорт всех необходимых js-файлов в один, минимизация этого файла и создание source map;
- сбор html файла, перенос шрифтов, обработка (сжатие) картинок и автоматическое обновление страниц посредством Browser Sync.
Кроме этого чтобы эти задачи не запускать при изменении исходных файлов вручную, создадим ещё одну задачу "watch". Она будет отслеживать изменения файлов, и запускать определённые задачи автоматически.
Код файла "gulpfile.js" (при использовании Gulp 4):
"use strict"; /* пути к исходным файлам (src), к готовым файлам (build), а также к тем, за изменениями которых нужно наблюдать (watch) */ var path = { build: { html: "assets/build/", js: "assets/build/js/", css: "assets/build/css/", img: "assets/build/img/", fonts: "assets/build/fonts/" }, src: { html: "assets/src/*.html", js: "assets/src/js/main.js", style: "assets/src/style/main.scss", img: "assets/src/img/**/*.*", fonts: "assets/src/fonts/**/*.*" }, watch: { html: "assets/src/**/*.html", js: "assets/src/js/**/*.js", css: "assets/src/style/**/*.scss", img: "assets/src/img/**/*.*", fonts: "assets/srs/fonts/**/*.*" }, clean: "./assets/build/*" }; /* настройки сервера */ var config = { server: { baseDir: "./assets/build" }, notify: false }; /* подключаем gulp и плагины */ var gulp = require("gulp"), // подключаем Gulp webserver = require("browser-sync"), // сервер для работы и автоматического обновления страниц plumber = require("gulp-plumber"), // модуль для отслеживания ошибок rigger = require("gulp-rigger"), // модуль для импорта содержимого одного файла в другой sourcemaps = require("gulp-sourcemaps"), // модуль для генерации карты исходных файлов sass = require("gulp-sass"), // модуль для компиляции SASS (SCSS) в CSS autoprefixer = require("gulp-autoprefixer"), // модуль для автоматической установки автопрефиксов cleanCSS = require("gulp-clean-css"), // плагин для минимизации CSS uglify = require("gulp-uglify"), // модуль для минимизации JavaScript cache = require("gulp-cache"), // модуль для кэширования imagemin = require("gulp-imagemin"), // плагин для сжатия PNG, JPEG, GIF и SVG изображений jpegrecompress = require("imagemin-jpeg-recompress"), // плагин для сжатия jpeg pngquant = require("imagemin-pngquant"), // плагин для сжатия png rimraf = require("gulp-rimraf"), // плагин для удаления файлов и каталогов rename = require("gulp-rename"); /* задачи */ // запуск сервера gulp.task("webserver", function () { webserver(config); }); // сбор html gulp.task("html:build", function () { return gulp.src(path.src.html) // выбор всех html файлов по указанному пути.pipe(plumber()) // отслеживание ошибок.pipe(rigger()) // импорт вложений.pipe(gulp.dest(path.build.html)) // выкладывание готовых файлов.pipe(webserver.reload({ stream: true })); // перезагрузка сервера }); // сбор стилей gulp.task("css:build", function () { return gulp.src(path.src.style) // получим main.scss .pipe(plumber()) // для отслеживания ошибок.pipe(sourcemaps.init()) // инициализируем sourcemap .pipe(sass()) // scss -> css .pipe(autoprefixer()) // добавим префиксы.pipe(gulp.dest(path.build.css)) .pipe(rename({ suffix: ".min" })) .pipe(cleanCSS()) // минимизируем CSS .pipe(sourcemaps.write("./")) // записываем sourcemap .pipe(gulp.dest(path.build.css)) // выгружаем в build .pipe(webserver.reload({ stream: true })); // перезагрузим сервер }); // сбор js gulp.task("js:build", function () { return gulp.src(path.src.js) // получим файл main.js .pipe(plumber()) // для отслеживания ошибок.pipe(rigger()) // импортируем все указанные файлы в main.js .pipe(gulp.dest(path.build.js)) .pipe(rename({ suffix: ".min" })) .pipe(sourcemaps.init()) //инициализируем sourcemap .pipe(uglify()) // минимизируем js .pipe(sourcemaps.write("./")) // записываем sourcemap .pipe(gulp.dest(path.build.js)) // положим готовый файл.pipe(webserver.reload({ stream: true })); // перезагрузим сервер }); // перенос шрифтов gulp.task("fonts:build", function () { return gulp.src(path.src.fonts) .pipe(gulp.dest(path.build.fonts)); }); // обработка картинок gulp.task("image:build", function () { return gulp.src(path.src.img) // путь с исходниками картинок.pipe(cache(imagemin([ // сжатие изображений imagemin.gifsicle({ interlaced: true }), jpegrecompress({ progressive: true, max: 90, min: 80 }), pngquant(), imagemin.svgo({ plugins: [{ removeViewBox: false }] }) ]))) .pipe(gulp.dest(path.build.img)); // выгрузка готовых файлов }); // удаление каталога build gulp.task("clean:build", function () { return gulp.src(path.clean, { read: false }) .pipe(rimraf()); }); // очистка кэша gulp.task("cache:clear", function () { cache.clearAll(); }); // сборка gulp.task("build", gulp.series("clean:build", gulp.parallel("html:build", "css:build", "js:build", "fonts:build", "image:build"))); // запуск задач при изменении файлов gulp.task("watch", function () { gulp.watch(path.watch.html, gulp.series("html:build")); gulp.watch(path.watch.css, gulp.series("css:build")); gulp.watch(path.watch.js, gulp.series("js:build")); gulp.watch(path.watch.img, gulp.series("image:build")); gulp.watch(path.watch.fonts, gulp.series("fonts:build")); }); // задача по умолчанию gulp.task("default", gulp.series("build", gulp.parallel("webserver","watch")));
Код файла "gulpfile.js" содержит комментарии. С помощью них поясняется что выполняет тот или иной фрагмент инструкций.
Создание задачи в Gulp выполняется очень просто:
// создание gulp задачи (nametask – название задачи) gulp.task("nametask", function() { // действия, которые должна выполнить задача... });
Задачи в gulp построены очень просто. Их каркас действий в большинстве случаев можно представить так:
- получить данные из исходных файлов;
- обработать исходные данные посредством gulp плагинов;
- сохранить полученный результат (файлы) в каталог "build".
Если используете Gulp 3, то содержимое файла "gulpfile.js" должно быть следующим:
"use strict"; /* параметры для gulp-autoprefixer */ var autoprefixerList = [ "Chrome >= 45", "Firefox ESR", "Edge >= 12", "Explorer >= 10", "iOS >= 9", "Safari >= 9", "Android >= 4.4", "Opera >= 30" ]; /* пути к исходным файлам (src), к готовым файлам (build), а также к тем, за изменениями которых нужно наблюдать (watch) */ var path = { build: { html: "assets/build/", js: "assets/build/js/", css: "assets/build/css/", img: "assets/build/img/", fonts: "assets/build/fonts/" }, src: { html: "assets/src/*.html", js: "assets/src/js/main.js", style: "assets/src/style/main.scss", img: "assets/src/img/**/*.*", fonts: "assets/src/fonts/**/*.*" }, watch: { html: "assets/src/**/*.html", js: "assets/src/js/**/*.js", css: "assets/src/style/**/*.scss", img: "assets/src/img/**/*.*", fonts: "assets/srs/fonts/**/*.*" }, clean: "./assets/build/*" }; /* настройки сервера */ var config = { server: { baseDir: "./assets/build" }, notify: false }; /* подключаем gulp и плагины */ var gulp = require("gulp"), // подключаем Gulp webserver = require("browser-sync"), // сервер для работы и автоматического обновления страниц plumber = require("gulp-plumber"), // модуль для отслеживания ошибок rigger = require("gulp-rigger"), // модуль для импорта содержимого одного файла в другой sourcemaps = require("gulp-sourcemaps"), // модуль для генерации карты исходных файлов sass = require("gulp-sass"), // модуль для компиляции SASS (SCSS) в CSS autoprefixer = require("gulp-autoprefixer"), // модуль для автоматической установки автопрефиксов cleanCSS = require("gulp-clean-css"), // плагин для минимизации CSS uglify = require("gulp-uglify"), // модуль для минимизации JavaScript cache = require("gulp-cache"), // модуль для кэширования imagemin = require("gulp-imagemin"), // плагин для сжатия PNG, JPEG, GIF и SVG изображений jpegrecompress = require("imagemin-jpeg-recompress"), // плагин для сжатия jpeg pngquant = require("imagemin-pngquant"), // плагин для сжатия png rimraf = require("gulp-rimraf"), // плагин для удаления файлов и каталогов rename = require("gulp-rename"); /* задачи */ // запуск сервера gulp.task("webserver", function () { webserver(config); }); // сбор html gulp.task("html:build", function () { return gulp.src(path.src.html) // выбор всех html файлов по указанному пути.pipe(plumber()) // отслеживание ошибок.pipe(rigger()) // импорт вложений.pipe(gulp.dest(path.build.html)) // выкладывание готовых файлов.pipe(webserver.reload({ stream: true })); // перезагрузка сервера }); // сбор стилей gulp.task("css:build", function () { return gulp.src(path.src.style) // получим main.scss .pipe(plumber()) // для отслеживания ошибок.pipe(sourcemaps.init()) // инициализируем sourcemap .pipe(sass()) // scss -> css .pipe(autoprefixer({ // добавим префиксы browsers: autoprefixerList })) .pipe(gulp.dest(path.build.css)) .pipe(rename({ suffix: ".min" })) .pipe(cleanCSS()) // минимизируем CSS .pipe(sourcemaps.write("./")) // записываем sourcemap .pipe(gulp.dest(path.build.css)) // выгружаем в build .pipe(webserver.reload({ stream: true })); // перезагрузим сервер }); // сбор js gulp.task("js:build", function () { return gulp.src(path.src.js) // получим файл main.js .pipe(plumber()) // для отслеживания ошибок.pipe(rigger()) // импортируем все указанные файлы в main.js .pipe(gulp.dest(path.build.js)) .pipe(rename({ suffix: ".min" })) .pipe(sourcemaps.init()) //инициализируем sourcemap .pipe(uglify()) // минимизируем js .pipe(sourcemaps.write("./")) // записываем sourcemap .pipe(gulp.dest(path.build.js)) // положим готовый файл.pipe(webserver.reload({ stream: true })); // перезагрузим сервер }); // перенос шрифтов gulp.task("fonts:build", function () { return gulp.src(path.src.fonts) .pipe(gulp.dest(path.build.fonts)); }); // обработка картинок gulp.task("image:build", function () { return gulp.src(path.src.img) // путь с исходниками картинок.pipe(cache(imagemin([ // сжатие изображений imagemin.gifsicle({ interlaced: true }), jpegrecompress({ progressive: true, max: 90, min: 80 }), pngquant(), imagemin.svgo({ plugins: [{ removeViewBox: false }] }) ]))) .pipe(gulp.dest(path.build.img)); // выгрузка готовых файлов }); // удаление каталога build gulp.task("clean:build", function () { return gulp.src(path.clean, { read: false }) .pipe(rimraf()); }); // очистка кэша gulp.task("cache:clear", function () { cache.clearAll(); }); // сборка gulp.task("build", [ "clean:build", "html:build", "css:build", "js:build", "fonts:build", "image:build" ]); // запуск задач при изменении файлов gulp.task("watch", function () { gulp.watch(path.watch.html, ["html:build"]); gulp.watch(path.watch.css, ["css:build"]); gulp.watch(path.watch.js, ["js:build"]); gulp.watch(path.watch.img, ["image:build"]); gulp.watch(path.watch.fonts, ["fonts:build"]); }); // задача по умолчанию gulp.task("default", [ "build", "webserver", "watch" ]);
- Инструкция по эксплуатации велосипеда Инструкция по эксплуатации велосипеда silverback
- Термостатический клапан: виды и способы установки
- Бамбук комнатный: фото, уход в домашних условиях Выделяют трудности при выращивании этого растения
- Подчеркивающий индивидуальность самшит (буксус): размножение, посадка, уход в домашних условиях и фото