cult3

Setting up Sass with Grunt

Nov 18, 2013

Table of contents:

  1. Installing Grunt
  2. Creating the GruntFile
  3. Grunt configuration
  4. Setting a project banner
  5. Setting up Sass
  6. Watching for changes
  7. Loading Grunt plugins
  8. Grunt tasks
  9. Conclusion

In last week’s tutorial, we started looking at Grunt as a tool to automate a lot of the repetitive jobs of building a web application. Stuff like compiling Sass, linting Javascript, minification and concatenation are all jobs that we can automate using a tool like Grunt.

Last week’s tutorial was an overview of the benefits of Grunt as well as a quick setup to show you how easy it is to get started. In this week’s tutorial I want to start to scratch the surface of a full Grunt setup to really show you the power of Grunt. This week I will be looking at setting up Sass, and configuring Grunt to do some nice little jobs for us.

So if you are knew to Grunt and you haven’t already read last week’s introductory tutorial, go read that now!

Installing Grunt

Just as a quick refresher from last time, I’ll go over setting up Grunt in a project.

First we need to set up the Grunt CLI:

npm install -g grunt-cli

Next we need to install Grunt:

npm install -g grunt-init

Finally, to generate the package.json file, simply run:

npm init

This should prompt you with some questions about your project. Don’t worry about your answers, you can easily change any of them once the package.json file has been generated.

Once the generator had finished I modified my package.json file slightly. This is what my file ended up looking like:

{
    "name": "Cribbb",
    "title": "I need to think of a catchy title",
    "url": "https://cribbb.com",
    "author": "Philip Brown",
    "copyright": "2013",
    "version": "0.0.1",
    "license": "GNU",
    "repository": {
    "type": "git",
    "url": "git://github.com/cribbb/cribbb.git"
}

Finally we can actually install Grunt into this project. Run the following command in Terminal:

npm install grunt -save-dev

This should add the following section into your package.json file:

{
    "devDependencies": {
        "grunt": "~0.4.1"
    }
}

For a full explanation into how installing dependencies works, have a read of last week’s tutorial.

Creating the GruntFile

Now that we have the package.json set up we need to create it’s partner in crime, the GruntFile.js file. This is just a regular Javascript file that we can create as you normally would.

/*!
 * Cribbb Gruntfile
 * https://cribbb.com
 * @author Philip Brown
 */

"use strict";

/**
 * Grunt Module
 */
module.exports = function (grunt) {};

Grunt configuration

The first thing to do is to create the Grunt configuration:

/**
 * Configuration
 */
grunt.initConfig({});

The Grunt configuration is used to set up how we want the various dependencies of the project to work. Each dependency will usually have a range of options that you can configure.

The first thing to do is to load the package.json file that we created earlier.

/**
 * Get package meta data
 */
pkg: grunt.file.readJSON('package.json'),

Remember, the GruntFile.js is just a regular Javascript file so loading the package.json file allows us to access the meta data through the pkg variable.

We can also set some additional variables to make working with file paths easier and to prevent repetition:

/**
 * Set project object
 */
project: {
    app: 'app',
    assets: '<%= project.app %>/assets',
    src: '<%= project.assets %>/src',
    css: [
    '<%= project.src %>/scss/style.scss'
    ],
    js: [
    '<%= project.src %>/js/*.js'
    ]
}

Setting a project banner

Have you ever seen the comment banners at the top of Open Source files? Generating these banners and automatically prepending them to our files is a really nice thing that Grunt can take care for us and it shows how powerful using our package meta data can be.

Add the following to your GruntFile:

/**
 * Project banner
 */
tag: {
    banner: '/*!\n' +
    ' * <%= pkg.name %>\n' +
    ' * <%= pkg.title %>\n' +
    ' * <%= pkg.url %>\n' +
    ' * @author <%= pkg.author %>\n' +
    ' * @version <%= pkg.version %>\n' +
    ' * Copyright <%= pkg.copyright %>. <%= pkg.license %> licensed.\n' +
    ' */'
}

Now whenever we need to generate a banner at the top of a file, we can effortlessly get Grunt to do it for us.

Setting up Sass

As I mentioned in a previous tutorial, Sass is my preprocessor of choice and fortunately Grunt has an excellent plugin for handling it.

To install Sass, simply run the following command in Terminal:

npm install grunt-contrib-sass -save-dev

Next add the following to your configuration options:

/**
 * Sass
 */
sass: {
    dev: {
        options: {
            style: 'expanded',
            banner: '<%= tag.banner %>',
            compass: true
        },
        files: {
            '<%= project.assets %>/css/style.css': '<%= project.css %>'
        }
    },
    dist: {
        options: {
            style: 'compressed',
            compass: true
        },
        files: {
            '<%= project.assets %>/css/style.css': '<%= project.css %>'
        }
    }
},

The Sass configuration is basically broken down into two sections, dev and dist for development and production. This allows us to set different options for the different outputs depending on the environment. For example, you will want your production stylesheets to be compressed, but whilst in development we would want the output which is generated to be expanded. You will also notice that I have specified that Compass should be loaded, and for the development branch I will also prepend the banner that we defined earlier.

Finally you must specify where the input and output files are located. The output is the first option and the input is the second.

For a full list of configuration options, take a look at the documentation.

Watching for changes

Running the grunt command every time you want to compile your Sass into CSS is going to get pretty tedious really quickly and kind of defeats the objective of automating things.

Instead of running things manually, we can set Grunt to “watch” our files for changes. This means whenever a file that we are watching is changed, we can automatically run a set of tasks.

To install the Watch dependency, run the following in Terminal:

npm install grunt-contrib-watch -save-dev

Next, add the following to your configuration:

/**
 * Watch
 */
watch: {
    sass: {
        files: '<%= project.src %>/scss/{,*/}*.{scss,sass}',
        tasks: ['sass:dev']
    }
}

Here we are basically saying, whenever a file that matches this pattern is changed, run this command. So whenever a file under the scss directory is updated, run the sass:dev task.

To keep things relatively simply I’ll only install Sass for this tutorial. In future tutorials I will cover adding additional plugins as I need them.

Loading Grunt plugins

Now that we have our configuration set up, we need to load the plugins. You might remember from last week where we had this line of code:

grunt.loadNpmTasks("grunt-contrib-uglify");

In order for the Grunt tasks to be run, we need to first load the plugins. Using the syntax above we would have to list out every plugin that we require. However instead of manually loading this plugins, we can load them dynamically using the matchdep package.

To install the matchdep package, run the following in Terminal:

npm install matchdep -save-dev

Next add the following line to your GruntFile:

/**
 * Load Grunt plugins
 */
require("matchdep").filterDev("grunt-*").foreach (grunt.loadNpmTasks);

This will now automatically load all of your Grunt plugins so you don’t have to manually list them out and keep that list up-to-date.

Grunt tasks

Finally we need to set up the task to run Grunt:

/**
 * Default task
 * Run `grunt` on the command line
 */
grunt.registerTask("default", ["sass:dev", "watch"]);

The default grunt task will run the dev branch of Sass and Watch. If you now save your GruntFile.js and run the grunt command in Terminal, you should see Sass compile and Grunt start watching your Sass files.

Now if you make a change to your Sass file, you will see the Sass task automatically run to recompile your Sass into CSS.

Conclusion

Grunt is an amazing tool for automating a lot of the repetitive tasks of Web Development. Things like compiling Sass or unit testing Javascript should automatically occur whenever a file is saved. Fortunately, Grunt can handle all of these little tasks for us.

Over the last two tutorials I’ve covered setting up Grunt in a project and adding Sass. However there is much more that you can accomplish with Grunt. When a project has a fast growing ecosystem like the one that Grunt has, you can guarantee that a lot of the problems you face will have already been solved.

Grunt is very much a staple of of my projects and has quickly found itself to be an extremely important tool in my box of tricks. In future posts I will be covering when I add new plugins to the project and how I configure things, but I probably won’t be dedicating any more full posts to Grunt specifically.

If you are looking for more information on setting up Grunt, I would highly recommend taking a look at FireShell. I’ve picked up a lot of really good practices from reading through the code, so I’m sure you will be able to learn a lot from it too!

This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.

Philip Brown

@philipbrown

© Yellow Flag Ltd 2024.