Static Version

Simplifying Chores with Grunt

Often in various stages of development we perform repetitive tasks e.g minification, compilation, unit testing, linting and we would definitely want to automate them. But each of these task require different configurations or installations. What if there is a system where in we can easily configure and run these tasks from a single place. Also it would be really nice if it gels well with Node.js system. Meet Grunt a task runner for simplifying chores. Apart from being simple Grunt ecosystem is huge and it's growing every day with literally hundreds of plugins to choose from.

Note that I will be using grunt task/plugin interchangeably which means the same.

Installation

In order to get started first we need to install grunt-cli.

npm install -g grunt-cli

This will install grunt command in your system. Note that this is different from the grunt task runner. Notice that we are installing grunt-cli in global scope. After this install grunt in your package.json directory using

npm install grunt --save-dev

This will install grunt task runner and add it to devDependencies section of your package.json.

You can also install grunt by adding it to devDependency of package.json manually and run npm install

Why is grunt-cli required

grunt-cli is used to run the local grunt task runner using node.js require() system. This helps us in running grunt task runner from any sub-directory of your project. The job of the grunt-cli is simple: run the version of grunt which has been installed next to a Gruntfile i.e under the node_modules directory.

What is a Gruntfile

Gruntfile is where we define configurations for the task which we are planning to run. Think of it as what package.json is for npm. Gruntfile is always placed at the top level of project along with package.json. Below is a directory structure showing the Gruntfile for project.

Gruntfile

Please note that though we call it Gruntfile name of the file will be Gruntfile.js.

Installing a grunt task

Best way to learn something is by example. Lets take a very common task of minifying set of css files and then combine them to a single file.

As I have mentioned earlier grunt has an excellent repository of plugins to perform these tasks, which can be found on http://gruntjs.com/plugins. Doing a quick search on this page gives cssmin as one of the best plugin for it. To see installation and configuration instructions, head over to the plugins npm page.

As given in the npm page of cssmin install it with the given below command.

npm install grunt-contrib-cssmin

Now we have successfully installed a grunt task, its time to use it in Gruntfile.

Using a task in Gruntfile

Since we have installed our task into our project its time to dive into Gruntfile and use the task in it. Below is the Gruntfile for our task. Most of the parts could be understood with the comments given.

Gruntfile.js
module.exports = function(grunt) {

 
// files to be minified and combined
 
var cssFiles = [
   
'public/css/file1.css',
   
'public/css/file2.css'
 
];

 
// this is where all the grunt configs will go
  grunt
.initConfig({
   
// read the package.json
   
// pkg will contain a reference to out pakage.json file use of which we will see later
    pkg
: grunt.file.readJSON('package.json'),

   
// configuration for the cssmin task
   
// note that this syntax and options can found on npm page of any grunt plugin/task
    cssmin
: {
     
// options for css min task
      options
:{
       
// banner to be put on the top of the minified file using package name and todays date
       
// note that we are reading our project name using pkg.name i.e name of our project
        banner
: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
     
},
      combine
: {
       
// options for combining files
       
// we have defined cssFiles variable to hold our file names at the top
        files
: {
         
// here key part is output file which will our <package name>.min.css
         
// value part is set of input files which will be combined/minified
         
'public/css/<%= pkg.name %>.min.css': cssFiles
       
}
     
}
   
}

 
}); // end of configuring the grunt task

 
// Load the plugin that provides the "cssmin" task.
  grunt
.loadNpmTasks('grunt-contrib-cssmin');

 
// Default task(s).
  grunt
.registerTask('default', ['cssmin']);
 
// cssmin task
  grunt
.registerTask('buildcss', ['cssmin']);

};

Note that we have to wrap your Gruntfile in module.exports. Lets understand the various important parts of this Gruntfile.

Understanding parts of Gruntfile

grunt.initConfig - Block where we define configurations specific to a plugin. In the example above i have shown configuration for 1 plugin but there could be more than 1 in it. e.g

cssmin: {
 
// task/plugin 1
},
uglify
: {
 
// task/plugin 2
}

grunt.loadNpmTasks - This is where we load the task/plugin.

grunt.registerTask - This is where we register the task. I am going to explain this part a bit more in the next section where we will learn to run this task of ours.

Running a grunt task

Before diving into how to run a grunt task lets understand grunt.registerTask in depth. Recall from our Gruntfile below block of code.

// Default task(s).
// This is the task which runs if we just execute grunt command
  grunt
.registerTask('default', ['cssmin']);
 
// cssmin task
 
// This is a custom task which runs if we execute grunt buildcss command
  grunt
.registerTask('buildcss', ['cssmin']);

A Gruntfile is executed either by running grunt command or grunt task-name. In our Gruntfile when we say grunt.registerTask('default', ['cssmin']), this is what is going to run when we only type grunt command and that's why name of the task is default . Also note that second argument to grunt.registerTask is an array of tasks to be run.

grunt.registerTask('buildcss', ['cssmin']) defines a new custom task and perform cssmin. We can also add some other task to it. This is what is going to run when we type grunt buildcss command.

To summarize

grunt

Runs default grunt task defined with grunt.registerTask('default', ['cssmin'])

grunt buildcss

Runs custom grunt task defined with grunt.registerTask('buildcss', ['cssmin'])

Running any of these commands should generate our minified file with the following output.

Output

In both the cases, second argument to grunt.registerTask can have more than one task. For example if we have JavaScript minification task uglify in our Gruntfile with default grunt.registerTask as:

grunt.registerTask('default', ['cssmin','uglify'])

This tutorial has just touched base on Grunt but there are in-numerous things which we can do using it. I use Grunt for css/js minification, templates compilation, appending cache busting param, string replacements etc. Grunt community has built tasks for almost everything we do. So check them out and use them to automate your chores.


View the discussion thread.blog comments powered byDisqus