Статьи

Простой Gulp’y Workflow For Sass

Недавно я отвечал за оптимизацию Sass в довольно большом Rails-проекте, и одна из самых важных вещей, которую нужно было сделать, — это улучшить время компиляции. Из-за имеющейся архитектуры Sass и того факта, что Ruby Sass (в данном случае через конвейер ресурсов Rails) имеет тенденцию работать медленно при работе с огромным количеством файлов, компиляция таблиц стилей может занять до 40 секунд. Поговорим о быстром процессе разработки. ?

Моя идея состояла в том, чтобы отойти от конвейера активов и использовать скорость LibSass . Чтобы сделать вещи проще, я решил пойти с простым рабочим процессом Gulp . Это был первый раз, когда я использовал Gulp, и я должен сказать, что это был довольно приятный опыт (что касается Гранта, насколько я понимаю).

В этой короткой статье давайте кратко рассмотрим, как настроить рабочий процесс Gulp’y для работы с Sass. Вот что мы будем включать:

  • Неудивительно, что компиляция Sass с LibSass
  • Создание исходных карт для облегчения отладки
  • Префикс CSS с помощью автопрефиксера
  • Генерация документации Sass с помощью SassDoc

Компиляция Sass

Смотреть AtoZ: Sass
Узнайте Sass буква за буквой

Первое, что нужно сделать, это установить зависимости и создать Gulpfile.js . Нам понадобится Gulp (без дерьма, Шерлок), но также Gulp-sass для компиляции наших таблиц стилей:

 $ npm install gulp gulp-sass --save-dev 

Эта строка указывает npm установить оба пакета gulp-sass и gulp-sass качестве зависимостей разработки. Теперь вы можете найти их в объекте devDependencies вашего package.json . И Gulpfile.js :

 var gulp = require('gulp'); var sass = require('gulp-sass'); 

Вау, это было коротко. Теперь нам нужно запустить Sass (фактически gulp-sass ) в нашей папке стилей.

 var input = './stylesheets/**/*.scss'; var output = './public/css'; gulp.task('sass', function () { return gulp // Find all `.scss` files from the `stylesheets/` folder .src(input) // Run Sass on those files .pipe(sass()) // Write the resulting CSS in the output folder .pipe(gulp.dest(output)); }); 

Это оно! Теперь мы можем скомпилировать наши таблицы стилей, используя LibSass, благодаря очень минимальной задаче Gulp. Что об этом? Мы можем передать параметры в gulp-sass для компиляции таблиц стилей в расширенном режиме и для вывода ошибок в консоли:

 var sassOptions = { errLogToConsole: true, outputStyle: 'expanded' }; gulp.task('sass', function () { return gulp .src(input) .pipe(sass(sassOptions).on('error', sass.logError)) .pipe(gulp.dest(output)); }); 

Добавление исходных карт

Все идет нормально. А как насчет генерации исходных карт? Если вы не знаете, что такое исходные карты, это в основном способ сопоставить сжатые производственные источники с расширенными источниками разработки, чтобы упростить отладку живого кода. Они вообще не ограничены CSS, исходные карты можно использовать и в JavaScript.

У нас есть хорошая статья об исходных картах здесь, в SitePoint . Не стесняйтесь прочитать его перед тем, как продолжить, если вам не хватает понимания исходных карт.

Итак, чтобы добавить генерацию исходных карт в нашу задачу, нам нужно установить gulp-sourcemaps :

 $ npm install gulp-sourcemaps --save-dev 

А теперь давайте оптимизируем нашу задачу:

 var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); // ... variables gulp.task('sass', function () { return gulp .src(input) .pipe(sourcemaps.init()) .pipe(sass(sassOptions).on('error', sass.logError)) .pipe(sourcemaps.write()) .pipe(gulp.dest(output)); }); 

По умолчанию gulp-sourcemaps записывает исходные карты в скомпилированные CSS-файлы. В зависимости от настроек проекта, мы можем захотеть записать их в отдельные файлы, и в этом случае мы можем указать путь относительно gulp.dest() назначения sourcemaps.write() функции sourcemaps.write() например:

 gulp.task('sass', function () { return gulp .src(input) .pipe(sourcemaps.init()) .pipe(sass(sassOptions).on('error', sass.logError)) .pipe(sourcemaps.write('./stylesheets/maps')) .pipe(gulp.dest(output)); }); 

Привлечение Автопрефиксера на вечеринку

Я не буду вдаваться в подробности о том, почему использование Autoprefixer лучше, чем написание поставщика вручную (или с миксином, который в основном то же самое), но примерно Autoprefixer — это этап пост-обработки, означающий, что он фактически обновляет уже скомпилированные таблицы стилей для добавления соответствующие префиксы на основе современной базы данных и заданной конфигурации. Другими словами, вы сообщаете Autoprefixer, какие браузеры вы хотите поддерживать, и он добавляет только соответствующие префиксы в таблицы стилей. Нулевое усилие, отличная поддержка (пожалуйста, напомните мне запатентовать эту ключевую фразу)

Чтобы включить Autoprefixer в наш рабочий процесс Gulp’y, нам нужно только передать его после того, как Sass сделает свое дело. Затем Autoprefixer обновляет таблицы стилей для добавления префиксов.

Во-первых, давайте установим его (вы уже поняли суть):

 $ npm install gulp-autoprefixer --save-dev 

Затем мы добавим это к нашей задаче:

 var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); // ... variables gulp.task('sass', function () { return gulp .src(input) .pipe(sourcemaps.init()) .pipe(sass(sassOptions).on('error', sass.logError)) .pipe(sourcemaps.write()) .pipe(autoprefixer()) .pipe(gulp.dest(output)); }); 

Прямо сейчас мы работаем с конфигурацией по умолчанию от Autoprefixer, которая

  • Браузеры с долей рынка более 1%,
  • Последние 2 версии всех браузеров,
  • Firefox ESR,
  • Опера 12.1

Мы можем использовать нашу собственную конфигурацию следующим образом:

 var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); // ... variables var autoprefixerOptions = { browsers: ['last 2 versions', '> 5%', 'Firefox ESR'] }; gulp.task('sass', function () { return gulp .src(input) .pipe(sourcemaps.init()) .pipe(sass(sassOptions).on('error', sass.logError)) .pipe(sourcemaps.write()) .pipe(autoprefixer(autoprefixerOptions)) .pipe(gulp.dest(output)); }); 

Отпустите документы!

Последний, но не менее важный инструмент для добавления в наш рабочий процесс — генерация документации Sass с помощью SassDoc . SassDoc для Sass, что JSDoc для JavaScript: инструмент документации. Он анализирует ваши таблицы стилей в поисках блоков комментариев, документирующих переменные, миксины, функции и заполнители.

Если ваш проект использует SassDoc (он должен!), Вы можете добавить автоматическую генерацию документации в ваш рабочий процесс Gulp.

Крутая вещь с SassDoc заключается в том, что он может передаваться напрямую в Gulp, потому что его API совместим с Gulp. Так что на самом деле у вас gulp-sassdoc плагина gulp-sassdoc .

 npm install sassdoc --save-dev 
 var gulp = require('gulp'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); var autoprefixer = require('gulp-autoprefixer'); var sassdoc = require('sassdoc'); // ... variables gulp.task('sass', function () { return gulp .src(input) .pipe(sourcemaps.init()) .pipe(sass(sassOptions).on('error', sass.logError)) .pipe(sourcemaps.write()) .pipe(autoprefixer(autoprefixerOptions)) .pipe(gulp.dest(output)) .pipe(sassdoc()) // Release the pressure back and trigger flowing mode (drain) // See: http://sassdoc.com/gulp/#drain-event .resume(); }); 

Обратите внимание, что в зависимости от размера вашего проекта и количества документированных элементов, запуск SassDoc может занять до нескольких секунд (насколько я заметил, редко выше 3), поэтому вам может потребоваться отдельная задача для это.

 gulp.task('sassdoc', function () { return gulp .src(input) .pipe(sassdoc()) .resume(); }); 

Опять же, мы используем конфигурацию по умолчанию, но мы можем использовать нашу собственную, если захотим.

 var sassdocOptions = { dest: './public/sassdoc' }; gulp.task('sassdoc', function () { return gulp .src(input) .pipe(sassdoc(sassdocOptions)) .resume(); }); 

я наблюдаю, слежу за тобой

Есть еще кое-что, что мы можем сделать перед уходом: создать задачу по watch . Смысл этой задачи состоит в том, чтобы отслеживать изменения в таблицах стилей для их повторной компиляции. Это очень удобно при работе со стороной Sass проекта, поэтому вам не нужно запускать задачу sass вручную при каждом сохранении файла.

 gulp.task('watch', function() { return gulp // Watch the input folder for change, // and run `sass` task when something happens .watch(input, ['sass']) // When there is a change, // log a message in the console .on('change', function(event) { console.log('File ' + event.path + ' was ' + event.type + ', running tasks...'); }); }); 

Вот еще одна причина, по которой я рекомендую не включать SassDoc в задачу sass: вы, вероятно, не хотите восстанавливать документы каждый раз, когда вы касаетесь таблицы стилей. Скорее всего, это то, что вы хотите сделать при сборке или отправке, возможно, с помощью ловушки перед фиксацией.

Добавляем последний штрих

Последнее, но важное, о чем нужно подумать: запуск sass в задаче по умолчанию.

 gulp.task('default', ['sass', 'watch' /*, possible other tasks... */]); 

Массив, переданный в качестве второго аргумента функции task(..) является списком зависимых задач. По сути, он говорит Gulp запускать эти задачи перед выполнением задачи, указанной в качестве третьего аргумента (если есть).

Кроме того, мы могли бы, вероятно, создать задачу prod которую можно было бы запустить прямо перед развертыванием в производство (возможно, с помощью git hook). Эта задача должна:

  • Скомпилируйте Sass в сжатом режиме
  • Префикс CSS с автоматическим исправлением
  • Восстановить документацию SassDoc
  • Избегайте любых исходных карт
 gulp.task('prod', ['sassdoc'], function () { return gulp .src(input) .pipe(sass({ outputStyle: 'compressed' })) .pipe(autoprefixer(autoprefixerOptions)) .pipe(gulp.dest(output)); }); 

Последние мысли

Вот и все, ребята! Всего за пару минут и несколько строк JavaScript нам удалось создать мощный маленький рабочий процесс Gulp. Вы можете найти полный файл здесь . Что бы вы добавили к этому?