Конфигурация сборщика проектов Gulp
Конфигурация gulp
Итак, вернемся к файлу конфигурации gulp.
Первый блок — мы подгружаем модули в переменные, чтобы удобно было с ними работать в процессе настройки сборщика:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // -------------------------------------------------------------------- // Plugins // -------------------------------------------------------------------- var gulp = require("gulp"), sass = require("gulp-sass"), concat = require("gulp-concat"), clean = require("gulp-clean"), plumber = require("gulp-plumber"), minify_css = require("gulp-minify-css"), uglify = require("gulp-uglify"), sourcemaps = require("gulp-sourcemaps"), prefix = require("gulp-autoprefixer"), jshint = require("gulp-jshint"), connect = require('gulp-connect-php'), rename = require('gulp-rename'), spritesmith = require('gulp.spritesmith'), browserSync = require("browser-sync"); |
В случае, если какой из модулей не загружен и не может быть найден — при запуске сборщика мы получим ошибку невозможности загрузить тот или иной модуль. Краткое описание модулей:
- gulp-sass — работа с scss, sass
- gulp-concat — объединение файлов
- gulp-clean — удаление файлов
- gulp-plumber — отлавливает ошибки gulp и позволяет не завершать работу сборщика
- gulp-minify-css — минифицирует css файлы
- gulp-autoprefixer — добавляем вендорные префиксы в css
- gulp-jshint — jshint для gulp, следит за правильностью js кода
- gulp-connect-php — обработка php файлов (необходим php интерпретатор на машине)
- gulp-rename — механизм переименования файлов
- gulp.spritesmith — генерация спрайтов и css к ним
- browser-sync — live-reload функционал без использования расширений браузера
У каждого модуля есть ряд настроек, которые лучше смотреть в официальной документации, т.к. инструменты постоянно совершенствуются.
Далее идет блок настроек, где указаны пути в нашем приложении:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // -------------------------------------------------------------------- // Settings // -------------------------------------------------------------------- var src = { main_sass: "src/scss/main.scss", sass: "src/scss/**/*.scss", css: "src/css/**/*.css", js: "src/js/**/*.js", libs: "src/libs/**/*.js", static: "src/static/**", sprites: "src/sprites/*.*", tmp: "src/tmp" }; var output = { dir: "build/", css: 'main.css', js: 'main.js', sprite: 'images/sprite.png' }; |
Сразу хочу заметить, что конструкция вида **/*.js означает поиск файлов во вложенных папках
Далее определяем обработчик ошибок и перенос статичных файлов из папки static в корень проекта
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // -------------------------------------------------------------------- // Error Handler // -------------------------------------------------------------------- var onError = function (err) { console.log(err); this.emit('end'); }; // -------------------------------------------------------------------- // Task: Static // -------------------------------------------------------------------- gulp.task('static', function () { return gulp.src(src.static) .pipe(plumber({ errorHandler: onError })) .pipe(gulp.dest('build')) }) |
Прошу заметить, что в каждой задаче task мы задаем обработчик ошибок.
Далее настраиваем склейку спрайтов. Я не представляю — как я раньше не пользовался подобным инструментом. Сейчас его использую во всех проектах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // -------------------------------------------------------------------- // Task: Sprite // -------------------------------------------------------------------- gulp.task('sprite', function () { var spriteData = gulp.src(src.sprites) .pipe(plumber({ errorHandler: onError })) .pipe(spritesmith({ imgName: 'sprite.png', imgPath: output.sprite, cssTemplate: 'src/spritesmith.cssTemplate', cssName: 'sprite.scss', algorithm: 'binary-tree', cssFormat: 'css' //cssFormat: 'scss_maps', //cssVarMap: function (sprite) { // sprite.name = 's-' + sprite.name //} })); spriteData.img.pipe(gulp.dest('build/images')); return spriteData.css.pipe(gulp.dest('src/scss/_includes')); }); |
Мы можем настроить вывод в чистый css, а можно сделать в scss, это удобно, когда мы не можем элементу задать конкретный класс, поэтому через scss наследуем правило из сгенерированного файла. Более детальную настройку можно посмотреть в документации плагина. Так же тут используется шаблон css файла, находящийся в файле
1 | src/spritesmith.cssTemplate |
Для исключения каких-либо ошибок при сборке — я предпочитаю чистить директорию build и tmp перед следующими задачами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // -------------------------------------------------------------------- // Task: Clean build // -------------------------------------------------------------------- gulp.task('clean', function () { gulp.src(output.dir + "/*") .pipe(clean()); }) // -------------------------------------------------------------------- // Task: Clean tmp // -------------------------------------------------------------------- gulp.task('clean-tmp', function () { gulp.src(src.tmp + "/*") .pipe(clean()); }) |
Далее переходим к обработке css стилей
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // -------------------------------------------------------------------- // Task: Sass // -------------------------------------------------------------------- gulp.task('prestyle', ['clean-tmp'], function () { return gulp.src(src.main_sass) .pipe(plumber({ errorHandler: onError })) .pipe(sass({style: 'expanded'})) .pipe(prefix('last 2 version')) .pipe(gulp.dest(src.tmp)) }) gulp.task('style', ['prestyle'], function () { return gulp.src([src.tmp + '/main.css', src.css]) .pipe(plumber({ errorHandler: onError })) .pipe(concat(output.css)) .pipe(gulp.dest(output.dir)) .pipe(minify_css({keepSpecialComments: 0, restructuring: false, processImport: false})) .pipe(rename({suffix: '.min'})) .pipe(gulp.dest(output.dir)) .pipe(browserSync.reload({stream: true})); }); |
Как видно, задачи две. При том prestyle вызывается из style. В prestyle мы делаем сборку scss, далее мы склеиваем все css файлы, минифицируем и в конечном результате получаем всего один файл.
Переходим к js компиляции
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // -------------------------------------------------------------------- // Task: JS // -------------------------------------------------------------------- gulp.task('prejs', ['clean-tmp'], function () { return gulp.src(src.js) .pipe(plumber({ errorHandler: onError })) .pipe(jshint()) .pipe(jshint.reporter('default')) .pipe(concat('all.js')) .pipe(uglify({compress: true})) .pipe(gulp.dest(src.tmp)) }); gulp.task('js', ['prejs'], function () { return gulp.src([src.libs, src.tmp + '/all.js']) .pipe(plumber({ errorHandler: onError })) //.pipe(sourcemaps.init()) .pipe(concat(output.js)) .pipe(gulp.dest(output.dir)) //.pipe(sourcemaps.write()) .pipe(uglify({compress: true})) .pipe(rename({suffix: '.min'})) .pipe(gulp.dest(output.dir)) .pipe(browserSync.reload({stream: true})); }); |
Здесь аналогично 2 задачи, одна из которых вызывается по цепочке. Аналогично, сначала обрабатываем свой файл со скриптами, затем объединяем его с файлами библиотек и компилируем в один файл. Во время разработки полезно генерировать sourcemap файлы, которые позволяют легко отлаживать ошибки. В продакшн их лучше убрать.
Далее идет уже техническая настройка gulp — настройка вотчеров (следим за измененными файлами и выполняем необходимые задачи), настройка сервера livereload и обработки php файлов и создание порядка запуска задач при первом запуске gulp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // -------------------------------------------------------------------- // Task: Watch // -------------------------------------------------------------------- gulp.task('watch', function () { gulp.watch(src.static, ['static']); gulp.watch([src.js, src.libs], ['js']); gulp.watch([src.sass, src.css], ['style']); gulp.watch([src.sprites], ['sprite']); }); // -------------------------------------------------------------------- // Task: Server // -------------------------------------------------------------------- gulp.task('server', function () { console.log('START server'); connect.server({base: './build', open: false}, function () { browserSync({ proxy: 'localhost:8000', //tunnel: true, open: false, logFileChanges: false, logLevel: 'silent' }); }); }); // -------------------------------------------------------------------- // Task: Default // -------------------------------------------------------------------- gulp.task('default', ['clean', 'server', 'static', 'sprite', 'style', 'js', 'watch']); |
На следующей странице приведен полный листинг кода всех необходимых файлов.