Конфигурация сборщика проектов 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']); | 
На следующей странице приведен полный листинг кода всех необходимых файлов.