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.
Image may be NSFW.
Clik here to view.
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.
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.
Image may be NSFW.
Clik here to view.
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.