It’s very rare when repetitive tasks are a welcome addition to any part of our life, personal or professional. More often than not, during our development cycles and processes we encounter more than one task that is performed with glaring regularity. With so much to develop, control and manage, it can be a little daunting if you add up the time spent on such tasks – time that could arguably be better spent elsewhere.

Enter Grunt.js, a free open source JavaScript task runner powered by Node.js. Grunt aims to alleviate such repetitive tasks by allowing you to create singular or batched processes to manage these for you from the command line. Written in JavaScript, anyone with basic JS knowledge can get up and running with the Grunt command line quickly. It’s also a highly extensible framework, with an ever-growing number of plug-ins contributed by the development community.

In this tutorial we’ll install the Grunt command line interface tool, set up our local project environment to use the library and install some useful plug-ins to assist us with minifying and managing JavaScript and CSS files ready for production use. Welcome to Grunt!

Step-by-step

01 Prerequisites
Grunt and the installation of any of its plug-ins is managed through the Node.js package manager. As such, your development machine must have Node.js installed. If you have not already done so, make sure you head over to nodejs.org/download and download the installer.

02 Install Grunt CLI
With Node.js installed we have access to the package manager via the command line. Open up a Terminal or CMD window and run the following command to install the Grunt CLI (Command Line Interface). The –g tag will install it globally, adding it to your system path and making it accessible from any directory on the machine.

npm install g grunt-cli

03 Prepare your project

To set up Grunt processes within a new or existing project directory, two specific files are required – both of which need to live in the root of the project location. Create a new file in the root called package.json. At the very least this must contain name and version fields. We’ll also add in the devDependencies field for later use.

The second required file is the Gruntfile, which is used to configure or define tasks and to load any Grunt plug-ins we have requested within this project. Create Gruntfile.js (or Gruntfile. coffee) in the root directory of your project. Inside of this add the ‘wrapper’ function, which is used by every Gruntfile and plug-in. This will hold our configuration data.

module.exports = function(grunt) {
};

05 Install Grunt

Let’s add our first plug-in, which is actually Grunt itself. With the Terminal window open in the project directory, enter the command to install the package from the manager. Here we are not using the –g flag to install them globally, but instead choosing to save them locally and automatically add them to the devDependencies section in the package.json file.

npm install grunt –save-dev

06 Dependency added

Once any npm install command has been run to add a Grunt plug-in with the –save- dev flag used, the system knows that this should be added as a dependency for development. It then adds the plug-in in question to the devDependency configuration section of the package.json file. Open the file in your editor in order to see the updates.

“devDependencies”: {
“grunt”: “~0.4.1”
}

07 Uglify plug-in

Let’s add another plug-in into the system. Once again, open up your Terminal window within the project directory and install a new plug-in, grunt-contrib-uglify. Make sure to use the –save-dev flag again so that it is added to the package.json file for you. This plug-in can be used to minify files, which is perfect for any JavaScript files we have.

npm install grunt-contrib-uglify –save-dev

08 Grunt config initialisation

Before we can add any tasks to our Gruntfile, we first need to make sure we define the grunt.initConfig method, which initialises a configuration object for the current project. This sits directly within the wrapper function. Add this code into the Gruntfile to declare the configuration object. Our task definitions and configuration information will go inside of this function.

grunt.config.init({
});

09 Uglify configuration

We can now add in our individual task configuration. Each plug-in has its own config options, which can normally be found on the GitHub or Grunt plug-in pages. Define the uglify configuration. Set the build option to reference the source directory where our files reside, and the destination directory into which the minified version will be placed.

When ‘uglifying’ or processing any files, many Grunt plug-ins will let you define a banner, which can be any block of text, and add it to the top of the processed file for you. This is particularly great for the marking and storing of dates or configuration data in the file. Add the banner option as shown in the following code snippet to the uglify configuration.

With the task config defined, we now need to load the task into the system so that Grunt knows what to reference when a task is run. This is achieved easily by adding in a method into the Gruntfile to load the locally installed npm plug- ins. Simply define the same plug-in name used when you installed it via the command line.

grunt.loadNpmTasks(‘grunt-contrib-uglify’);

12 Run the task

Let’s run the task. Open up the Terminal window and navigate to within the project directory. To run a task, we need to call Grunt followed by the name of the task to run, which we configured in the Gruntfile. Once complete, the Terminal window will give you a response from the process.

grunt uglify

13 Minified JavaScript file

Our uglify task was set to minify (or uglify) a specific JavaScript file in our source directory and place the revised version into a destination directory ready for production. Open up the dest/js/script.js file in a code editor. You should be able to see the minified code and the inclusion of a date stamp at the top, provided by the banner setting.

14 CSS minification

Let’s add a new plug-in to our local project. With a Terminal window open, install a new plug-in called grunt-contrib-cssmin and save as a dev dependency to update the package.json file. We want to keep our CSS files as small as possible for production, and this plug-in was written just for the task.

npm install grunt-contrib-cssmin –save-dev

15 Configure the task

Open up Gruntfile.js in your code editor. We can now add in the task configuration for the freshly installed plug-in. We can once more make use of the banner setting to add in the date of the compilation. We are also choosing to minify all CSS files within the selected directory, renaming them as ‘combined.min.css’ in the output directory.

With more than one task defined we would have to run each task individually from the command line. We can combine as many tasks as we wish and create a default that will run when we write ‘grunt’ or ‘grunt default’ in the command line. This new task will run each task specified, saving us a lot of time.

grunt.registerTask(‘default’,
[‘uglify’,’cssmin’]);

grunt

17 Watches files

While it’s incredibly powerful to be able to run tasks as and when they are required, some developers may find it beneficial to have the ability to perform tasks on files when they have been added or updated. There is a Grunt plug-in to manage this too, so let’s install it in the same way as we have installed all the others throughout this tutorial.

npm install grunt-contrib-watch –save-dev

18 Configure the watch

The watch plug-in can be configured, as with many of the other plug-ins, to watch a specific directory or set of files in the project. Here we are watching for a change to any of the JavaScript files within the src directory. Once detected, we are running the uglify task to process the minification of JS files. Make sure you remember to load the task as well.

To start the watch task, open your Terminal window within the project directory and call Grunt watch. The output will let you know that it is waiting for file changes. Once any are detected, the chosen task will be run and the actions processed as defined in the task configuration.

grunt watch

20 Manage variables

We have referenced the src and dest directories numerous times within the Gruntfile. While this is acceptable, we can reduce the duplication of hardcoded values and actually set these locations within our package.json file. Add the following below the devDependencies object. The package.json file is a great place to set reusable values.

“srcDir”: “src/”,
“destDir”: “dest/”

21 Load JSON file

Open up Gruntfile.js in your code editor. We can now replace any instances of hardcoded directory paths to use the variables in the package.json file. First, we need to set a variable to hold the JSON contents of our .json file using a built-in method from the grunt core file API.

grunt.config.init({
pkg: grunt.file.readJSON(‘package.json’),
// The rest of the gruntfile...

22 Change path references

We can now change any references to our directory paths. Find and replace all instances of ‘src/’ and replace it with and ‘dest/’ can be replaced with . When running our tasks, the template strings will convert to the relative paths set in the package.json file, reducing the amount of repetition found within our code. That’s really all there is to it – now many of your repetitive tasks will be taken care of!