Блог начинающего фронтендера

Учимся использовать сборщик пакетов Gulp

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

Чем он помогает мне?

  • Конкатенация HTML. Позволяет разделить внутрененнее устройство HTML и внешние повторящиеся части, такие как header и footer
  • Конкатенация и минификация JS. Позволяет на выходе получить один минифицированный JS с source-map
  • Конкатенация, компиляция, минификация SCSS. Создает минифицированный объединенный CSS
  • Расстановка префиксов браузеров в CSS
  • Оптимизация изображений
  • Расстановка файлов по нужным папкам

Установка Gulp

Для работы Gulp необходимо наличие Node.js и npm

Создаем папку нашего проекта "2u4u" и переходим в нее через терминал:

mkdir 2u4u
cd 2u4u

Вводим команду:

npm init

Можно нажимать Enter, тогда все значения будут подставлены по умолчанию. Данная команда генерирует файл package.json, который содержит информацию о проекте, и, что самое важное, зависимостях. Данный файл появится в папке проекта.

Для установки зависимостей необходимо набрать команду вида:

npm install gulp --save-dev

где gulp это название плагина. Чтобы установить сразу несколько плагинов, то можно набрать команду вида:

npm install gulp gulp-watch gulp-autoprefixer --save-dev

Все плагины будут перечислены в блоке devDependencies. После этого файл package.json будет иметь следующий вид:

{
  "name": "2u4u",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^5.0.0",
    "gulp-watch": "^5.0.0"
  }
}

А в папке проекта появится папка node_modules.

Плагины

Список плагинов, которые я использую/использовал с своих проектах:

  • gulp-watch - следит за изменением в файлах
  • gulp-autoprefixer - использует autoprefixer для добавления префиксов браузеров. Подробнее
  • gulp-uglify - минифицирует JS, удаляя лишние пробелы и переводы строк
  • gulp-sass - компилирует SCSS в CSS
  • gulp-sourcemaps - создает source-map минифицированного файла
  • gulp-rigger - позволяет подключать к одном файлу другие файлы. Подробнее
  • gulp-clean-css - минифицирует CSS, удаляя лишние пробелы и переводы строк
  • gulp-imagemin - оптимизирует изображения, можно уменьшать их и сжимать
  • imagemin-pngquant - в дополнение к gulp-imagemin сжимает png файлы
  • gulp-replace - позволяет заменить текст в файлах перед его публикацией
  • gulp-header - позволяет добавить текст в заголовке файла. Использую для добавление информацию style.css моей темы Wordpress
  • rimraf - пакет для удаления файлов
  • browser-sync - создает локальный сервер, доступ к адресу возможен с любого устройства подключенного к этой же wi-fi сети, после изменения файла сразу обновляет страницу в браузере

gulp-uglify:

Можно настроить какие браузеры необходимы. В своих проектах я использую autoprfixer для 4 последних версий:

.pipe(prefixer({
    browsers: ['last 4 versions']
}))

gulp-rigger:

Позволяет подключать к файлу другие файлы. Например позволяет задать один head для всех html и подключать его. Например, вот таким образом можно подключить файл head.html в index.html:

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

Определим файловую структуру проекта и добавим:

  • папка build будет содержать собранный проект
  • папка src будет содержать все исходники проекта
    • папка scss - содержит стили (scss и css файлы)
    • папка images - содержит картинки
    • папка js - содержит Javascript скрипты
    • папка fonts - содержит шрифты
  • gulpfile.js - конфигурация проекта

gulpfile.js

Вызываем все плагины:

'use strict';

var gulp        = require('gulp'),
    watch       = require('gulp-watch'),
    //тут вызываются все необходимые плагины в зависимости от проекта
    browserSync = require("browser-sync"),
    reload      = browserSync.reload;//функция перезагрузки BrowserSync

Создаем JS объект, в котором укажем для удобства все пути

var path = {
	//папка куда складываются готовые файлы
    build: { 
        html: 'build/',
        js: 'build/js/',
        css: 'build/css/',
        img: 'build/images/',
        fonts: 'build/fonts/'
    },
    //папка откуда брать файлы
    src: { 
        html: 'src/[^_]*.html', 
        js: 'src/js/*.js', 
        style: 'src/scss/*.scss', 
        img: 'src/images/**/*.{jpg,jpeg,png}', 
        fonts: 'src/fonts/**/*.*'
    },
    //указываем после измененя каких файлов нужно действовать
    watch: { 
        html: 'src/**/*.html',
        js: 'src/js/**/*.js',
        style: 'src/scss/**/*.{scss,css}',
        img: 'src/images/**/*.*',
        fonts: 'src/fonts/**/*.*'
    },
    clean: './build'
};

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

  • *.* - выбрать все файлы в указанной папке;
  • *.scss - выбрать все файлы с указанным разрешение в указанной папке;
  • *.{scss,css} - выбрать все файлы с указанными разрешениями в указанной папке;
  • */*.scss — выбрать все файлы с указанным расширением в этой папке и всех дочерних папках;
  • [^_]*.scss — выбрать все файлы кроме файлов с указанным расширение в этой м;
  • {main,additional}.scss — выбрать только перечисленные файлы в этой папке;

Переменная с настройками сервера

var config = {
    server: {
        baseDir: "./build" //из какой папки показывать
    },
    tunnel: true,
    host: 'localhost', 
    port: 9000,
    logPrefix: "2u4u"
};

Сборка файлов

В общем случае в фунцию gulp.task передается два параметра: название и функция:

gulp.task('taskname', function () { //тут указывается имя задачи. В нашем случае task
    gulp.src(tasksrcpath) //tasksrcpath - ссылка на источник файлов
        .pipe(gulp.dest(taskdestpath)); //taskdestpath - ссылка куда положить файлы
});

Создадим задачи для сборки файлов нашего проекта:

gulp.task('html:build', function () {
    gulp.src(path.src.html) 
        .pipe(rigger()) //проходим через rigger
        .pipe(gulp.dest(path.build.html))
        .pipe(reload({stream: true})); //перезагружаем сервер
});

gulp.task('js:build', function () {
    gulp.src(path.src.js) 
        .pipe(rigger()) 
        .pipe(sourcemaps.init()) //инициализация source-map
        .pipe(uglify()) //минификация JS файла
        //.pipe(sourcemaps.write()) //запись source-map
        .pipe(gulp.dest(path.build.js))
        .pipe(reload({stream: true}));
});

gulp.task('style:build', function () {
    gulp.src(path.src.style)
        .pipe(sourcemaps.init())
        .pipe(sass()) //компиляция sass файла 
        .pipe(prefixer({ 
            browsers: ['last 4 versions'] //добавление префиксов для 4-ех последних версия браузеров
        })) 
        .pipe(cssmin()) //минификация css файла
        .pipe(sourcemaps.write())
        .pipe(gulp.dest(path.build.css))
        .pipe(reload({stream: true}));
});

gulp.task('image:build', function () {
    gulp.src(path.src.img)
        .pipe(imagemin({ //сжатие картинок
            progressive: true,
            use: [pngquant()],
            interlaced: true
        }))
        .pipe(gulp.dest(path.build.img))
        .pipe(reload({stream: true}));
});

gulp.task('fonts:build', function() {
    gulp.src(path.src.fonts)
        .pipe(gulp.dest(path.build.fonts)) //шрифты просто копируем
});

В этом проекте для подготовки отдельного style.css файла для wordpress я добавил еще один таск, который добавляет в начало файла данные для темы wordpress, а так же меняет пути для шрифтов:

gulp.task('style:buildwp', function () {
    gulp.src(path.src.style)
        .pipe(sourcemaps.init())
        .pipe(sass())
        .pipe(prefixer({
            browsers: ['last 4 versions']
        }))
        .pipe(cssmin())
        .pipe(sourcemaps.write())
        .pipe(replace( '../fonts/', './fonts/') ) //заменяем ссылки
        .pipe(header('/*\nTheme Name: 2u4u\nVersion: 1.0\nDescription: My 2u4u theme\nAuthor: UU\nAuthor URI: http://2u4u.ru\n*/\n')) //добавляем данные в самом начале файла

        .pipe(gulp.dest(path.wp.css)) //отдельная папка для получившегося css
        .pipe(reload({stream: true}));
});

Создадим основной таск сборки всех сборок:

gulp.task('build', [
    'html:build',
    'js:build',
    'style:buildwp',
    'style:build',
    'fonts:build',
    'image:build',
    'copycss'
]);

Таск слежения за изменением файлов:

gulp.task('watch', function(){
    watch([path.watch.html], function(event, cb) {
        gulp.start('html:build');
    });
    watch([path.watch.style], function(event, cb) {
        gulp.start('style:build');
    });
    watch([path.watch.style], function(event, cb) {
        gulp.start('style:buildwp');
    });
    watch([path.watch.js], function(event, cb) {
        gulp.start('js:build');
    });
    watch([path.watch.img], function(event, cb) {
        gulp.start('image:build');
    });
    watch([path.watch.fonts], function(event, cb) {
        gulp.start('fonts:build');
    });
});

Таск запуска сервера:

gulp.task('webserver', function () {
    browserSync(config);
});

Таск для очистки папки проекта. Будет доступен при вызове gulp clean в терминале:

gulp.task('clean', function (cb) {
    rimraf(path.clean, cb);
});

Дефолтный таск, будет срабатывать при вызове gulp и активировать таски сборки, запуска сервера и слежения за изменениями:

gulp.task('default', ['build', 'webserver', 'watch']);

Полный код gulpfile.js

Полный код package.json

'use strict';

			var gulp        = require('gulp'),
			    watch       = require('gulp-watch'),
			    prefixer    = require('gulp-autoprefixer'),
			    uglify      = require('gulp-uglify'),
			    sass        = require('gulp-sass'),
			    sourcemaps  = require('gulp-sourcemaps'),
			    rigger      = require('gulp-rigger'),
			    cssmin      = require('gulp-clean-css'),
			    imagemin    = require('gulp-imagemin'),
			    pngquant    = require('imagemin-pngquant'),
			    rimraf      = require('rimraf'),
			    replace     = require('gulp-replace'),
			    browserSync = require("browser-sync"),
			    header      = require('gulp-header'),
			    reload      = browserSync.reload;

			var path = {
			    build: { 
			        html: 'build/',
			        js: 'build/js/',
			        css: 'build/css/',
			        img: 'build/images/',
			        fonts: 'build/fonts/'
			    },
			    src: { 
			        html: 'src/[^_]*.html', 
			        js: 'src/js/*.js', 
			        style: 'src/scss/*.scss', 
			        img: 'src/images/**/*.{jpg,jpeg,png}', 
			        fonts: 'src/fonts/**/*.*'
			    },
			    watch: { 
			        html: 'src/**/*.html',
			        js: 'src/js/**/*.js',
			        style: 'src/scss/**/*.{scss,css}',
			        img: 'src/images/**/*.*',
			        fonts: 'src/fonts/**/*.*'
			    },
			    clean: './build'
			};

			var config = {
			    server: {
			        baseDir: "./build"
			    },
			    tunnel: true,
			    host: 'localhost',
			    port: 9000,
			    logPrefix: "2u4u"
			};

			gulp.task('html:build', function () {
			    gulp.src(path.src.html) 
			        .pipe(rigger()) 
			        .pipe(gulp.dest(path.build.html))
			        .pipe(reload({stream: true}));
			});

			gulp.task('js:build', function () {
			    gulp.src(path.src.js) 
			        .pipe(rigger()) 
			        .pipe(sourcemaps.init())
			        .pipe(uglify())
			        //.pipe(sourcemaps.write())
			        .pipe(gulp.dest(path.build.js))
			        .pipe(reload({stream: true}));
			});

			gulp.task('style:build', function () {
			    gulp.src(path.src.style)
			        .pipe(sourcemaps.init())
			        .pipe(sass())
			        .pipe(prefixer({ 
			            browsers: ['last 4 versions']
			        })) 
			        .pipe(cssmin())
			        .pipe(sourcemaps.write())
			        .pipe(gulp.dest(path.build.css))
			        .pipe(reload({stream: true}));
			});

			gulp.task('style:buildwp', function () {
			    gulp.src(path.src.style)
			        .pipe(sourcemaps.init())
			        .pipe(sass())
			        .pipe(prefixer({
			            browsers: ['last 4 versions']
			        }))
			        .pipe(cssmin())
			        .pipe(sourcemaps.write())
			        .pipe(replace( '../fonts/', './fonts/') )
			        .pipe(header('/*\nTheme Name: 2u4u\nVersion: 1.0\nDescription: My 2u4u theme\nAuthor: UU\nAuthor URI: http://2u4u.ru\n*/\n'))

			        .pipe(gulp.dest(path.wp.css))
			        .pipe(reload({stream: true}));
			});

			gulp.task('image:build', function () {
			    gulp.src(path.src.img)
			        .pipe(imagemin({
			            progressive: true,
			            use: [pngquant()],
			            interlaced: true
			        }))
			        .pipe(gulp.dest(path.build.img))
			        .pipe(reload({stream: true}));
			});

			gulp.task('fonts:build', function() {
			    gulp.src(path.src.fonts)
			        .pipe(gulp.dest(path.build.fonts))
			});

			gulp.task('build', [
			    'html:build',
			    'js:build',
			    'style:build',
			    'style:buildwp',
			    'image:build',
			    'fonts:build'
			]);

			gulp.task('watch', function(){
			    watch([path.watch.html], function(event, cb) {
			        gulp.start('html:build');
			    });
			    watch([path.watch.style], function(event, cb) {
			        gulp.start('style:build');
			    });
			    watch([path.watch.style], function(event, cb) {
			        gulp.start('style:buildwp');
			    });
			    watch([path.watch.js], function(event, cb) {
			        gulp.start('js:build');
			    });
			    watch([path.watch.img], function(event, cb) {
			        gulp.start('image:build');
			    });
			    watch([path.watch.fonts], function(event, cb) {
			        gulp.start('fonts:build');
			    });
			});

			gulp.task('webserver', function () {
			    browserSync(config);
			});

			gulp.task('clean', function (cb) {
			    rimraf(path.clean, cb);
			});

			gulp.task('default', ['build', 'webserver', 'watch']);
{
	  "name": "2u4u",
	  "version": "1.0.0",
	  "description": "",
	  "author": "",
	  "license": "ISC",
	  "dependencies": {},
	  "devDependencies": {
	    "browser-sync": "^2.23.6",
	    "gulp": "^3.9.1",
	    "gulp-autoprefixer": "^5.0.0",
	    "gulp-clean-css": "^3.9.2",
	    "gulp-header": "^2.0.1",
	    "gulp-imagemin": "^4.1.0",
	    "gulp-replace": "^0.6.1",
	    "gulp-rigger": "^0.5.8",
	    "gulp-sass": "^3.1.0",
	    "gulp-sourcemaps": "^2.6.4",
	    "gulp-uglify": "^3.0.0",
	    "gulp-watch": "^5.0.0",
	    "imagemin-pngquant": "^5.0.1"
	  }
	}
Поделиться
Отправить
Отправить