Musings from Someone Discovering PostCSS

I originally wrote this piece about PostCSS as an internal post for my team at RP3 Agency, but I believe it might have relevance for front-end developers everywhere.

The new hotness in the CSS world is something called “PostCSS”, which I haven’t completely figured out yet but am getting there. Basically, things that happen after your Sass (or whatever) is done and has created a true CSS file go into this ecosystem. Think autoprefixer (for automatically entering browser vendor prefixes) and minification. (There’s even a school of thought that says this kind of thing can completely replace Sass, but I am so not there yet…)

In trying to bring a two-year-old project up to modern standards (the original project used things like Grunt which we don’t use anymore, having switched to Gulp), I’ve been trying to learn how to do things the “right” way.

So here’s the Gulp “styles” task I’ve come up with:

var gulp = require( 'gulp' ),
    sass = require( 'gulp-sass' ),
    rename = require( 'gulp-rename' ),
    plumber = require( 'gulp-plumber' ),
    gutil = require( 'gulp-util' ),
    sourcemaps = require( 'gulp-sourcemaps' ),
    postcss = require( 'gulp-postcss' ),
    autoprefixer = require( 'autoprefixer' ),
    csswring = require( 'csswring' ),
    del = require( 'del' ),
    concat = require( 'gulp-concat' ),
    uglify = require( 'gulp-uglify' ),
    connect = require( 'gulp-connect' );

gulp.task( 'styles', function() {

  gulp.src( __dirname + '/src/scss/*.scss' )
  .pipe( sourcemaps.init() )
  .pipe( plumber( function( err ) {
   var errorText = err.message + '\n\n' + err.source;
   gutil.log( errorText ) );
  } ) )
  .pipe( sass.sync() )
  .pipe( rename( function( path ) { path.extname = '.css' } ) )
  .pipe( postcss( [ autoprefixer( {
   browsers: [ 'last 2 versions', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4' ]
  } ), csswring() ] ) )
  .pipe( rename( function( path ) { path.extname = '.min.css' } ) )
  .pipe( sourcemaps.write( '.' ) )
  .pipe( gulp.dest( __dirname + '/dist/css/' ) )
  .pipe( connect.reload() );

} );

“autoprefixer” and “csswring” are plugins to PostCSS. I’m processing my Sass into CSS using “gulp-sass”, and then using PostCSS to do the autoprefixing and minification (in a sourcemap-friendly way, and that’s important as I’ll get to in a sec).

But I’ve come across a downside to this new flow. In the past I’ve written out two versions of the finished CSS file: an “expanded” one that’s more or less human readable for our development environments, and a minified version for production. In WordPress, for example, it’s easy to tell the theme which one to use and when based on whether we have debugging turned on or not.

But “csswring” was choking when trying to minify a CSS file that had a sourcemap, regardless of whether the sourcemap was inline or external. So if you’ll notice in this gulp task, the “expanded” CSS file never gets written out; the pipe goes directly from Sass file to minified CSS. But the sourcemap is written for the minified CSS, so if you’re working in Chrome, you can see where your property is being written in the Sass, like in this screenshot:

Screenshot of my project, demonstrating how sourcemaps are working on minified CSS.

It’s not a result that I’m 100% comfortable with, but I’m learning to stop worrying and love the minification. However, I’m wondering how this will fly in production. From one sense, there’s a certain amount of front-end civic responsibility in letting other developers see the source Sass you actually wrote, rather than just the processed and minified CSS that a computer crunched out. On the other hand, 99.9999% of your audience wouldn’t give one shit about that, so is the browser pulling down a sourcemap file that’s actually twice as large as the actual CSS file? Something else to figure out…


One thought on “Musings from Someone Discovering PostCSS

Leave a Reply

Your email address will not be published. Required fields are marked *