APEX, Sass & Sourcemaps integration

Update April-23-2016: Deprecated this package in favor of APEX Nitro.

This post is a follow-up to my previous post on how to integrate Gulp to your APEX workflow. This time we'll dig into an advanced Gulpfile that includes Sass & Sourcemaps.

I have given a presentation in January 2015 at @InsumSolutions office about it.

The source code is available here.


Changelog

1.3.0
  • Updated to gulp-concat 2.6.x
  • Updated to gulp-size 2.0.x
  • Updated to gulp-minify-css 1.2.x
  • Updated to gulp-imagemin 2.3.x
  • Updated to gulp-load-plugins 1.0.x-rc.1
1.2.0
  • Updated to gulp-uglify 1.2.x
  • Updated to gulp-rename 1.2.x
  • Updated to gulp-plumber 1.0.x
  • Updated to gulp-load-plugins 0.10.x
  • Updated to gulp-del 1.2.x
  • Updated to gulp-util 3.0.x
  • Updated to gulp-jshint 1.11.x
  • Updated to gulp-autoprefixer 2.3.x
  • Updated to gulp-minify-css 1.1.x
  • Updated to run-sequence 1.1.x
  • Updated to gulp 1.2.x
  • Updated to jshint-stylish 2.0.x
  • Updated to gulp-sourcemaps 1.5.x
1.1.0
  • Updated to gulp-sass 2.0.x
    • Which updates node-sass to 3.0.0
    • Which fixes Source maps: now work as expected with Autoprefixer

What is Sass?

Sass is a CSS Preprocessor, it adds features over your regular CSS. Browsers do not support Sass, so this new language needs to be compiled to CSS before it's deployed to your application.

So... it's a new programming language?

Yes, it's a "stylesheet programming language".

I'm skeptical, what's the big deal with Sass?

  • Requires less code
  • Requires less time to code
  • Offers better readability
  • Get more work done

but above all...

  • Maintainability +++++

Sass basics

I will not go into details on this. There are a million blogs covering the subject and I want to focus on the APEX integration. However, here's an overview of what you can accomplish with it:

Variables

Yes, you can write variables to your CSS. You can store colors, fonts, sizes, or any CSS property.

$my-font: Helvetica, sans-serif; 
$primary-color: #333; 

body { 
    font-family: $my-font; 
    color: $primary-color; 
} 

button { 
    background-color: $primary-color; 
}

Operators

Mathematics can be performed on any numeric values.

$container-width: 100%;
$number-of-columns: 4;

.container { 
    width: $container-width; 

    .column { 
        width: ($container-width / $number-of-columns;) 
    }
}

Nesting

Nesting CSS selectors are good for visualizing hierarchy. It removes the need for complicated prefixes.

The Inception Rule: Don’t go more than four levels deep.

ul { 
    li { 
        display: inline-block; 
    } 

    a { 
        display: block; 
        padding: 6px 12px; 
        text-decoration: none; 
    } 
}

Partials & Imports

Partials are SCSS files that contains only a part of your code. They can be imported in other SCSS files. It helps modularizing the code for better maintainability.

Partial files are prefixed with an underscore. It tells the compiler NOT to generate a standalone CSS file for your partial. The idea is to create lots of partials which are all going to be merged into one final CSS file.

/* _variables.scss */
$my-font: Helvetica, sans-serif; 
$primary-color: #333;

/* _general.scss */
body { 
    font-family: $my-font; 
    color: $primary-color; 
} 

/* _buttons.scss */
button { 
    background-color: $primary-color; 
}

/* app.scss */
@import 'variables';
@import 'general';
@import 'buttons';

Mixins

Mixins are very much like functions. It's a block of CSS code that you can simply reuse anywhere you need. It reduces code duplication.

@mixin size($width, $height: $width) { 
    width: $width; 
    height: $height; 
}

.sidebar {
    @include size(20%, 100%);
}

.main-content { 
    @include size(80%, 100%); 
}

.other { 
    @include size(50px); 
}

Extend

Let you share CSS properties between selectors. It helps keeping your code DRY with the concept of inheritance.

.message { 
    border: 1px solid #ccc; 
    padding: 10px; 
    color: #333; 
} 

.success { 
    @extend .message; 
    border-color: green; 
} 

.error { 
    @extend .message; 
    border-color: red; 
} 

The goal:

Let's use Sass in APEX now shall we?

Requirements:

  1. Understanding the Gulp methodology

Setup:

  1. Go to your Dropbox /Public/ folder and from there, fork my Github repository.
  2. Open a command prompt and cd to your project root folder
  3. From your project root folder, execute:
    • npm install

Usage

  1. From your project root folder, execute:
    • npm start
  2. Replace all the assets from my Github repo with your project assets
  3. Start coding your Sass in
    • /Public/apex-gulpfile-sass/client/assets/scss/

Usage in APEX:

As I explained in my previous post, you need a substitution string that points to your Dropbox Public folder.

Since your SCSS files were compiled to CSS by Gulp, all you need to do is including the final CSS file in your page template:
<link rel="stylesheet" href="&PATH.assets/css/app#MIN#.css">

Bonus: Sourcemaps

You might think that having a minified and compiled version of your source code affects debugging.

You know what I'm talking about! There's nothing more frustrating than having to deal with this:

What the hell right???

Notice I have included the #MIN# substitution string above. In debug mode, the file will show up as <link rel="stylesheet" href="&PATH.assets/css/app.css">. At least it'll be un-minified and readable...

Still, I have rigorously modularized my JS & CSS code, and the bug will show up in the compiled version, so I'll need to map the code back to the original source.

Here comes sourcemaps.

Sourcemaps are JSON files that links the compiled code to the original.

My Gulpfile is set up to attach a sourcemap to the un-minified version. They are exported directly in the /build/ folder right next to their compiled files.

Then, in app.css and app.js, Gulp adds a comment line at the end of the file to tell the browser to go look for it's sourcemap.

Look at this magic:

Instead of pointing at a meaningless compiled app.css or app.js, now the console looks at the original source code!

Seems like we have the best of both worlds...


Personally, Gulp, Sass and sourcemaps have changed the way I code. I believe it enforces a much more structured code, which is beneficial for everyone.

Do you like this development approach? Tell me what you think on Twitter!