Какие следует использовать плагины Gulp для более грамотной, с точки зрения эргономики ресурсов, уменьшения времени выполнения компиляции для организации таска.
Структура проекта следующая:
dev
|--component1 // компоненты проекта
|--component2
.....
|--scss
|--base // базовые подключаемые файлы с миксинами и прочим
|--elements // общие для всех страниц элементы оформления (кнопки и т.д.)
|--componets
|--component1
|--style.scss
|--component2
........
|--main.scss
Собирается все это так:
app
|--component1 // компоненты
|--css // отдельные стили каждого компонента
|--style.css
|--component2
.....
|--css // главный css
|--style.css
Таск sass для всего этого добра:
gulp.task('sass', function() {
return combiner(
gulp.src([
'dev/scss/main.scss' ,
'dev/scss/project components/**/*.scss'
]),
debug({title: 'src'}),
gulpIf(isDevelop, sourcemaps.init()),
sass( sassOptions ),
autoprefixer({
browsers: ['last 4 versions']
}),
gulpIf(isDevelop, sourcemaps.write()),
rename(function (path) {
path.dirname += '/css';
path.basename = 'main' ? 'style' : path.basename;
}),
gulpIf(!isDevelop, cleanCSS()),
gulp.dest('app'),
debug({title: 'dest'})
).on('error', notify.onError(function(err){
return {
title: 'sass',
message: err.message
}
}))
});
Сейчас при выполнении задачи в папку app помещаются все файлы из папок компонентов и главный файл стилей, независимо от того модифицировались они или нет. Хотелось бы что-бы манипуляции производились только с модифицируемыми файлами + непонятен вопрос с кешированием подключаемых через @import файлов.
Так же вопрос добавления удаления файлов и переписывания урлов к файлам подключаемым через css (картинки, шрифты...)
Буду признателен за подробные ответы и советы по организации таска.
Ответ
В идеале сборка должна быть такая, чтобы скомпилированный файлы, которые будут отдаваться пользователю, лежали отдельно от исходников и их можно было спокойно удалить при необходимости. К тому же, это позволит делать дополнительные оптимизации с исходными файлами и не менять пути в сборке.
Организация стилей
В целом, вы отлично организовали сборку стилей: организовали переменные окружения, добавили афтопрефиксер. Однако я бы посоветовал создать два отдельных таска для разного окружения, чтобы исключить дополнительные условия. К тому же, можно было бы в качестве путей добавить лишь 'dev/scss/main.scss' и в нем же делать @import'ы к остальным файлам.
Также бы посоветовал добавить livereload(), чтобы при изменении файлов ваш локальный сервер автоматически подгружал все изменения.
Также не пойму, как вы бы хотели, чтобы манипуляции производились только с модифицируемыми файлами. Если вы компилируете все scss-файлы в один main.css, то операции будут производиться над всем main.css, уже после сборки. Если вы хотите, чтобы манипуляции производились лишь с тем файлом, который вы меняете, нужно каждый из этих файлов подключать к документу и не объединять при разработке.
Организация картинок
Я бы посоветовал хранить исходные картинки отдельно и переносить их при компиляции в папку сборки (назовем ее public). Кроме обычного переноса было бы хорошо эти картинки сжать:
К примеру, картинки можно легко сжать без потери качества только за счет удаление exif-данных. На реальном сайте можно сократить размер картинок в среднем на 70%, что на современном сайте равняется примерно 4 МБ. Пример на gulp
var
gulp = require('gulp'),
imagemin = require('gulp-imagemin'),
imageminJR = require('imagemin-jpeg-recompress'),
imageminSvgo = require('imagemin-svgo');
// Optimizing images
gulp.task('imagemin', function() {
gulp.src('./img/**/*')
.pipe(imagemin([
imageminJR({
method: 'ms-ssim'
}),
imageminSvgo({
plugins: [
{removeViewBox: false}
]
})
]))
.pipe(gulp.dest('./public/img/'))
});
А для браузеров, которые понимают легковесный формат webp (формат разработан Google), можно сделать еще такой вариант изображений:
var
gulp = require('gulp'),
webp = require('gulp-webp');
// Generate Webp
gulp.task('webp', function() {
gulp.src('./img/**/*')
.pipe(webp())
.pipe(gulp.dest('./public/img/'))
});
Организация шрифтов
Тоже самое касается шрифтов, однако их нужно лишь перемещать в public
// Replace fonts
gulp.task('fonts', function () {
gulp.src('./fonts/text-font/*')
.pipe(gulp.dest('./public/fonts/'))
});
Создание иконочного шрифта
Предпочтительней было бы использование иконичного шрифта вместо картинок-спрайтов. И у этого метода есть ряд преимуществ:
Более меньший вес шрифта, чем спрайта;
Гибкость стилизации через CSS;
Меньший вес CSS;
Гибкий размер и ненадобность создание версий для Retina-дисплеев.
Для генерации иконочного шрифта я бы посоветовал такую комбинацию:
// Generate icon font
gulp.task('iconfont', function() {
var
fontName = 'icon-font',
cssClass = 'i';
// Исходные SVG-файлы
gulp.src(['./fonts/icon-font/*.svg'])
.pipe(iconfontCss({
fontName: fontName,
cssClass: cssClass,
path: './styl/mixins/icon-font.styl',
targetPath: '../../styl/components/font/icon-font.styl',
fontPath: '../fonts/'
}))
.pipe(iconfont({
fontName: fontName,
prependUnicode: true,
normalize: true,
formats: ['svg','ttf','woff','woff2']
}))
.pipe(gulp.dest('./public/fonts/'));
});
Миски для стилей, который берется из этой строки path: './styl/mixins/icon-font.styl' будет выглядеть так:
@font-face
font-family "<%= fontName %>"
src: url('<%= fontPath %><%= fontName %>.woff2') format('woff2'),
url('<%= fontPath %><%= fontName %>.woff') format('woff'),
url('<%= fontPath %><%= fontName %>.ttf') format('truetype'),
url('<%= fontPath %><%= fontName %>.svg#<%= fontName %>') format('svg')
[class*="i-"]
position relative
display inline-block
width 1em
height 1em
&:before
font 14px '<%= fontName %>'
font-size inherit
text-rendering auto
speak none
font-variant normal
text-transform none
color inherit
position absolute
top 50%
left 50%
transform translate(-50%, -50%)
<% _.each(glyphs, function(glyph) { %>
.<%= cssClass %>-<%= glyph.fileName %>:before
content "\<%= glyph.codePoint %>"
<% }); %>
После генерации шрифта все, что вам нужно будет сделать, это подключить сгенированный CSS к вашему сайту или инглудить его к главному CSS-файлу, а затем использовать таким образом: