Getting Started With Grunt

This tutorial will help you get started with Grunt, a useful Javascript task runner with automation capabilities.

We’re hearing a lot about GruntJS these days and you may wondering why. I’ve been using it for a couple of months and it helped me a great deal on many aspects of my developments. By reading this article, you’ll understand why Grunt should be part of your development process.

Why Grunt?

My development process already works, so why bother?

Let’s take an example. Inside your project, you probably have a bunch of files in their development format:

  • css files
  • js files
  • Images

When production time comes, you have to run it through your favorite concatenators, minifiers, optimizers, etc. And everything is working like a charm. But every time you have to make a change to your project, you have to run everything again and it’s beginning to become a hassle. This is where Grunt, the automated task runner, comes to your rescue!

The power of Grunt

Grunt tasks flow

Grunt will watch for changes in your project and automatically run the processes of your choice (sass or less processing, image optimization, code linting, page refresh etc…). And once production time comes, a simple command will also run all the specific commands you defined (concatenation, minification, unit tests, etc…). Once it is configured, you’ll never have to think about all that ever again! Isn’t it great?

All the tools you’re already using in your process are available as Grunt plugins. Compass, Sass, Less, JSLint, Optipng, uglify and many more. No more hassle, no more pain, Grunt lets you focus on the important part: your code. But like every new technology, there is a little downside: you have to learn how to use it. And that’s exactly what you will learn with this tutorial.

Prerequisites

Install Node.js

Grunt and Grunt plugins are installed and managed via npm, the Node.js package manager.
So the first thing you need to do is install Node.js.

Install Grunt CLI

To be able to use Grunt, you’ll need to install the command line interface:

npm install –g grunt-cli

The -g means that the program will be installed globally on your machine and not specifically for this project.

Setting up a new Grunt project

To be able to run Grunt, you will need to have 2 files in your project directory:

  • A gruntfile.js file, which is the Grunt configuration file.
  • A package.json file (used by npm) in which you’ll list Grunt and the Grunt plugins your project needs.

Package.json

The file in its bare bones state should look like this:

{
  "name": "introduction-to-grunt",
  "version": "0.1.0"
}

Now, let’s install grunt in our project directory. To install Grunt and its plugins, the easiest way is to run the command npm install <module> --save-dev. The npm module will be then saved locally. --save-dev tells npm to also update the package.json file, adding the module to the “devDependencies” section. Ok, let’s do this! Run this command:

npm install grunt --save-dev

Your package.json should look like this now:

{
  "name": "introduction-to-grunt",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "^0.4.5"
  }
}

Check your project directory, a folder named node_modules should have been created. It contains the Grunt module. Well, that was easy! But what about my teammates?

Anyone working on your project will be able to install all the node modules you specified in the package.json file by running npm install at the root folder. So no need to put the node_modules directory in your version control.

Gruntfile.js

Now let’s move on to the core configuration. The file in its bare bones state will look like this:

module.exports = function (grunt) {
   // Project configuration.
   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json')
   });
};

The “wrapper” function is the module.exports function in which we initialize Grunt and telling it to read our package.json file. Ok, basically, this does nothing; so let’s add a plugin to make it useful.

How to use a plugin

Let’s assume we are developping an awesome javascript application. When the app is finished, we want our code to be minified in production to make it faster to download. What we need is a minifier. If you take a look at the official Grunt plugins directory and search for “minify”, you’ll find the uglify plugin.

Adding the plugin

Let’s follow the plugin documentation and install it:

npm install grunt-contrib-uglify --save-dev

As usual, the package file and module directory will be updated.

Now let’s enable the plugin inside our gruntfile:

module.exports = function (grunt) {
   // Project configuration.
   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json')
   });

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

Our module is now ready to be used!

Configuring the plugin

Let’s say that our javascript is written in index.js inside the “js” folder. We want to uglify that file and save the ugilfied version as index.min.js.

We just need to add this to the initConfig function in our gruntfile:

uglify: {
   build: {
      src: 'js/index.js',
      dest: 'js/index.min.js'
   }
}

Now if we run the uglify command with grunt uglify it will already work like a charm.

The thing is, you’ll have way more than one task to run everytime you want to put your project in production. So let’s make a default task that will call all the tasks you need by using the registerTask command:

// Default tasks.
grunt.registerTask('default', ['uglify']);

To be sure we’re on the same page here, here what’s your gruntfile should look like:

module.exports = function (grunt) {
   // Project configuration.
   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      uglify: {
         build: {
            src: 'js/index.js',
            dest: 'js/index.min.js'
         }
      }
   });

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

   // Default tasks.
   grunt.registerTask('default', ['uglify']);
};

Now let’s run the grunt command. You’ll see an output looking like that:

Running "uglify:build" (uglify) task
>> 1 file created.

Done, without errors.

If you check your js folder, you’ll see an index.min.js file containing all your index.js code minified and ready to be deployed on production. Awesome! But for now we still have to run grunt manually each time we want to perform our tasks. And that’s when we need the most magical part of Grunt: automation!

Automating tasks

Now we would like Grunt to « watch » for changes to our files and run automatically when such change is detected. This is done by using the « watch » plugin. Let’s go to the plugin page and install it accordingly to the documentation.

npm install grunt-contrib-watch --save-dev

Let’s update our gruntfile to load the npm task:

grunt.loadNpmTasks('grunt-contrib-watch');

Now let’s set up our « watch » task so that it runs our uglify task whenever index.js file is modified. Just like before, we just need to follow the plugin documentation to do so. Here is the complete gruntfile updated:

module.exports = function (grunt) {
   // Project configuration.
   grunt.initConfig({
      pkg: grunt.file.readJSON('package.json'),
      uglify: {
         build: {
            src: 'js/index.js',
            dest: 'js/index.min.js'
         }
      },
      watch: {
         scripts: {
            files: ['js/index.js'],
            tasks: ['uglify']
         }
      }
   });

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

   grunt.loadNpmTasks('grunt-contrib-watch');

   // Default tasks.
   grunt.registerTask('default', ['uglify']);
};

Now, when we run the grunt watch command, we can just forget about it. Run the command and change your index.js file. Now save it and check out the command line, you should notice something like this:

>> File "js/index.js" changed.
Running "uglify:build" (uglify) task
>> 1 file created.

It shoud have succesfully created the minified version of index.js. That’s all there is to it! Everything is done automatically without having to run any command each time you change your code. Automation at its finest!

Conclusion

Now you should have a better view of what Grunt can do for you. All your development and production tasks automatically running without worrying about it. In my next tutorial, I will write a fully functional grunt configuration to help you really use it in your everyday development. I will be running Sass and Compass processing, image optimization, linting and many more.

You can download the full working project made with this article on Github: https://github.com/mvidailhet/getting-started-with-grunt

I hope you enjoyed this tutorial and found it useful. I’d love to hear about your thought about it in the comment section. Thanks for reading! And may code be with you!