Managing Dependencies: Getting Yeoman’s Grunt to work with Bundler and Compass

Ya it sounds like a joke... it ain’t.


As a front-end developer I’m looking for tools that make my job easier. Sometimes they are a pain to setup, but the outcome is better productivity and easier workflow. In this article I want to share my current front-end development environment and how I set it up.

In addition, this article will focus on how to link two sets of technology: Compass and Yeoman’s Grunt.js to provide a way to manage mixins, create a web app template, and watch/compile changes in a working directory.

Goals.

1. Manage and isolate my Mixins (Compass, Susy, Breakpoint) for SCSS with Bundler.
2. Use Compass to compile my SCSS to extend my CSS.
3. Use Yeoman + Yeoman’s Grunt to setup my web app and watch for changes of my working files.
This led to the question: How do I get Grunt in a Yeoman setup to activate Compass and its dependencies like Susy and Breakpoint, as well as, use Compass to compile my SCSS?
Styling — Bundler, Compass, and Mixins

On the styling side of things I’m partial to SCSS and Compass, as well as, a number of great add-ons/frameworks like Susy, for responsive grids and a mixin called Breakpoint.

Before using Yeoman, I would just use Compass for my projects.

Compass would compile SCSS, as well as, give me a ton of mixins that made my life easier.

I use Compass and other SCSS mixins with Bundler.

What is Bundler you might ask? Bundler handles Ruby Gem dependencies (Compass uses ruby gems). Whenever you want to include a mixin you download a Ruby Gem and then use a @include to include the SCSS mixin.

Make sure your Ruby and RVM (Ruby’s package manager) is up-to-date. Also make sure you correctly set your Ruby version. Putting in the following should return all your installed gems

gem list

Because Compass and its dependencies are managed through Ruby, you should see a list that includes your mixin libraries and frameworks. You should also see the associated version numbers. You can have multiple versions of each gem. This is a good thing, but it also can cause issues as certain Compass mixins need certain versions of Compass.

breakpoint (2.4.2)
bundler (1.6.3, 1.3.5)
More Gems ect.

You don’t want different global versions reeking havoc on each project so, you can use Bundler to create local, project based, groups of gems. Take a look at Bundler.

If you are wondering about setup, my Gemfile looks like this:

# A sample Gemfile
source ‘https://rubygems.org'
gem ‘compass’, ‘~>1.0.0.alpha.19'
gem ‘sass’, ‘~>3.3.8'
gem ‘breakpoint’, ‘~>2.4.2'
gem ‘susy’, ‘~>2.1.2'

If you are using Yeoman (I explain later in this article), make sure that this Gemfile is placed next to my Gruntfile.js or it will not be found and an error will be throw.

My Compass config.rb file looks like this:

require ‘rubygems’
require ‘bundler/setup’
# Require any additional compass plugins here.
require ‘compass’
require “breakpoint”;
require “susy”;

# Ignore these paths for now, I'll explain why they are like this near the end of this article. It's because this file is setup for Yeoman WebApp build
http_path = “/”
css_dir = “.tmp”
sass_dir = “app/styles”
images_dir = “app/images”
javascripts_dir = “app/scripts”

Those “require”s tell Bundler and Compass to include your mixins in the project. Essentially, I am letting Bundler give me a local version of gems scoped to my project and tell me if any of these files don’t play nice.

One way to install bundler and see the dependencies that are bundled is with the following in the app folder:

bundle install ——path vendor/bundle

However, you don’t have to run this install if using Yeoman with Grunt as it’s going to execute Bundler for you (I’ll explain in upcoming section).

As with any use of Compass I include these mixins in my SCSS file like this:

@import “compass/reset”;
@import “susy”;
@import “breakpoint”;

While Bundler seems like an extra step, it will save you when working on multiple projects with different versions of SCSS, Compass, and other mixins.

Yeoman. Grunt. Bower.

I’m a big fan of Yeoman. With a couple of key strokes you can create a working app with minimal setup.

If you haven’t used Yeoman, you should check it out. Play around installing some generators (templates for web apps). Yeoman does a lot. I’m not going to go into the nitty-gritty of setup, but this is a pretty good tutorial.

When not working the Angular Generator, I default to the WebApp Generator,

Grunt, a part of Yeoman, is also nifty as it does a lot of work for you, sizing images, compiling SCSS into CSS, refreshing the browser when changes are made to your working directories, ect..

Yeoman also includes Bower, also a great package manager for Javascript dependencies. i.e. handling jQuery and Modernizr.

Once again, each one these parts of the Yeoman scaffolding, is complicated enough for its own article, so I’ll refrain from giving full explinations (nor should I pretend that I know the intricacies of each).

The rest of the WebApp Generated files in a node.js server so you can watch for changes with

grunt watch 

serve your app with the command:

grunt serve

or build the project with

grunt build
So again, this really gets to the heart of things.

I want to use Bundler to manage and isolate my Ruby Gems (mixins) for Compass.

I want to use Compass to compile my SCSS, import my mixins, and in turn extend my SCSS.

I also want to use Yeoman + Yeoman’s Grunt to setup my web app and watch for changes of my files.

How do I get Grunt in a Yeoman setup to activate Compass and its dependencies and compile my SCSS?

Here is what you’ve been waiting for. . . or maybe not.

First thing is first, use Yeoman to generate a WebApp. The command is

yo

Choose your options for the build. I include the Modernizr option, but do not choose SCSS, since Compass will handle that.

Next, open the package.json folder created by the WebApp, this is a file that Node’s NPM uses to manage packages. Add the follwing line under devDependencies:

 “grunt-contrib-compass”: “~0.8.0"

Then in your directory run the following. (Make sure node.js and npm are up-to-date)

npm install

This uses Node Package Manager (NPM) to install a node module. This module lets Grunt work with Compass.

Next head over to Gruntfile.js. This is the Grunt script that’s going to need a bit of editing. We want to let Bundler/Compass handle SCSS mixins and compiling that for us, so that we can manage our gems and import unique mixins.

So comment out the following (this watches the css files and is not necessary):

 // styles: {
// files: [‘<%= config.app %>/styles/{,*/}*.css’],
// tasks: [‘newer:copy:styles’, ‘autoprefixer’]
// },

Replace it with the following:

 compass: {
files: ‘<%= config.app %>/styles/{,*/}*.{scss,sass}’,
tasks: [‘compass’]
},

You may have noticed this is located inside the Grunt Watch function. We are saying, “If an scss or sass file in the styles directory are changed run the Compass task.”

That task is the following and should be added below JShint or Mocha.

 compass: {
dist: {
options: {
//path to your config.rb file for Compass
config: ‘app/config.rb’,
//uses Bundler to handle ruby mixins
bundleExec: true,
//allows compass to overwrite css files when compiling
force: true
}
}
},

This is using the Compass contrib we just added to package.json to grab the Compass config.rb file and let Compass handle compiling our code when changes are made. It also tells Bundler to activate and use only the Gems in our Gemfile. Remember that part where we required a bunch of mixins? It’s handling that.

Once again, if you are using this setup, make sure that your Bundler Gemfile is placed next to my Gruntfile.js or it will not be found and an error will be throw. Also make sure you have the path to the config.rb file set correctly.

Also add “compass” to this chunk of code:

 concurrent: {
server: [
‘copy:styles’
],
test: [
‘copy:styles’
],
dist: [
‘compass’,
‘copy:styles’,
‘imagemin’,
‘svgmin’
]
}
Compass Configuration for Yeoman

As you might have noticed from when I was discussing Compass or when I linked the Grunt to config.rb, one thing you need to take care of when using Compass is where Compass needs to look to compile your SCSS files and where to put the output CSS files.

Those options should be located in the config.rb file. It often defaults to the the following.

http_path = “/”
css_dir = “.tmp/styles”
sass_dir = “app/styles”
images_dir = “app/images”
javascripts_dir = “app/scripts”

If using the Yeoman’s WebApp Generator it needs to look like this:

http_path = “/”
css_dir = “.tmp”
sass_dir = “app/styles”
images_dir = “app/images”
javascripts_dir = “app/scripts”

It looks like this because of the structure of the WebApp. One thing that is tricky is making your your CSS directory (css_dir) is set to .tmp. The Yeoman WebApp will be looking for css files in this directory by default and they need to be there.

Finishing strong

All that’s left is:

Grunt serve 

And begin working. Gem dependencies like Compass and SCSS mixins are isolated to your project with Bundler. Compass handles your compiling for you, while Yeomon structures your wep app and Grunt tells Compass when to compile.

It’s okay if you feel a little dizzy. I do to.

Email me when Pixels & Process publishes stories