Магия FontAwesome с postcss (или как делать @extend без @import)

Дубовской Александр
Team lead

Допустим у вас был монолитный styles.scss. И вы в него подгружали стили, которые назывались "_mystyle1.scss", "mystyle2.scss".

Но однажды, вам понадобилось одну очень тяжелую страницу по стилям выделить отдельно. Вы назвали ее "blog.scss" и хотите компилировать и подгружать отдельно. Все прекрасно, но вот беда - вы использовали fontawesome для scss, так чтобы в стилях удобно было писать:

.myclass {
  &:before {
    @extend .fa;
    @extend .fa-cogs;
  }
}

И все довольно удобно, вы можете использовать в ваших стилях все иконки из шрифта fontawesome (актуально для версии не старше 4.x). Но, теперь, если вы хотите разбить ваши .css файлы отдельно, вам придется либо тянуть в каждый из них библиотеку fontawesome стилей (а это ~ 44кб), либо ....

Вариантов нет, т.к. scss не позволяет использовать @extend без @import. А @import означает что все содержимое fontawesome будет дублироваться несколько раз. Какие варианты? Например - использовать PostCSS + postcss-font-awesome .

Пример gulpfile.js:

var gulp = require('gulp');
var postcss = require('gulp-postcss');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var sourcemaps = require('gulp-sourcemaps');
var livereload = require('gulp-livereload');
var sassGlob = require('gulp-sass-glob');
var lost = require('lost');
var fontawesome = require('postcss-font-awesome');

gulp.task('sass', function () {
  gulp.src([
    'scss/styles.scss',
    'scss/normalize.scss',
    'scss/styles/**/*.scss',
  ])
    .pipe(sourcemaps.init())
    .pipe(sassGlob())
    .pipe(sass())
    .pipe(postcss(
      [lost(), fontawesome]
    ))
    .pipe(autoprefixer({
      browsers: ['last 2 versions'],
      cascade: false
    }))
    .pipe(sass.sync().on('error', sass.logError))
    .pipe(sourcemaps.write('./maps'))
    .pipe(gulp.dest('./css/'))
});

Т.е. достаточно к рабочему конфигу добавить .pipe(postcss([lost(), fontawesome]))

После чего необходимо добавить в нашу MYTHEME.libraries.yml отдельно шрифт fontawesome. Пример:

global-styling:
  version: 1.0
  css:
    theme:
      https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css: { type: external, minified: true }
      css/styles.css: {}

Все, теперь мы можем использовать в наших стилях 

.myclass {
  &:before {
    font-awesome: code;
  }
}

И на выходе будем получать:

.myclass:before {
  font-family: FontAwesome;
  content: '\f121';
}