Grunt

Grunt is a JavaScript tool to create and automate project tasks. It solves the same problems as Ant for Java, Rake for Ruby, and so on, but in the JavaScript language.

It is widely used by the Node.js community, and it is gaining a lot of traction on all sorts of JavaScript projects.

We are going to use it to make our lives simpler and more automated, so that we can focus more on the development time!

Installation

Grunt is also a Node.js package, so its installation is pretty simple once you have Node.js installed (as explained in Chapter 4, Asynchronous Testing – AJAX).

Open up a terminal and invoke Node.js's package manager to install grunt's command-line interface and make it available globally:

$ npm install -g grunt-cli

At the project's root folder, install the grunt library:

$ npm install grunt

Once completed, you will have a grunt command available.

Project setup

To make our project grunt compatible, we need to create a Gruntfile. It is much like a Makefile, or a Rakefile, containing task definitions, but in JavaScript.

The Gruntfile should be named Gruntfile.js and should be placed in the project's root folder, containing the following skeleton:

module.exports = function(grunt) {
  grunt.initConfig({});
};

And this is it; we are ready to start adding helpful tasks to our project.

A RequireJS optimizer task

We are going to start by creating a task for our optimizer process. To make it simpler, we are going to use a grunt plugin, the grunt-contrib-requirejs.

Since it is also a Node.js package, we can install it with an NPM command. At the project root folder, execute the following command:

$ npm install grunt-contrib-requirejs

This will install the package and make it available for use inside our Gruntfile.

The first thing we need to do is load this plugin's tasks to our Gruntfile by adding a new line:

module.exports = function(grunt) {
  grunt.initConfig({});
  grunt.loadNpmTasks('grunt-contrib-requirejs'),
};

This will load a new grunt task called requirejs. But before we can start using it, we need to make a few configurations such as passing the same parameters to our Build.js file.

Add a new entry to grunt.initConfig:

grunt.initConfig({
  requirejs: {
    compile: {
      options: {
        mainConfigFile: 'src/RequireConfig.js',
        baseUrl: "src",
        name: "Boot",
        out: "build/Boot.js"
      }
    }
  }
});

You can notice that it is the same configuration parameters we had in the Build.js file. And since we are going to start using grunt for now on, you can even delete the old file.

All set, we can run our first grunt task and build our project:

$ grunt requirejs

This will perform the build, and create the resulting artifact, the same way as directly using the optimization script.

But we can still do better. We can make this requirejs task default, by adding another configuration parameter after we load the requirejs task inside our Gruntfile:

grunt.loadNpmTasks('grunt-contrib-requirejs'),
grunt.registerTask('default', ['requirejs']);

Now, all we have to do, to perform a build, is to call grunt.

$ grunt

A Jasmine task

We don't want to generate a build artifact without making sure that the specs are passing, after all we don't want to ship bugs to our production environment.

So let's create a new grunt task to run our specs and see how we can make it run before a build.

There are specific grunt plugins to run Jasmine specs, but we are going to use a different approach here. We want to use the same runner we specified earlier.

To execute the PhantomJS command from inside grunt, we are going to use the grunt-exec plugin;

Install it by invoking the familiar NPM command from the project folder:

$ npm install grunt-exec

Also, add its task in the Gruntfile, like we did with the requirejs plugin:

grunt.loadNpmTasks('grunt-exec'),

Next, we need to set up a new task to run PhantomJS. So add a new entry to the grunt configuration object:

grunt.initConfig({
  exec: {
    jasmine: {
      command: 'phantomjs run-jasmine.js SpecRunner.html'
    }
  }
});

Now, we are ready to start running our specs with a grunt command:

$ grunt exec:jasmine

This will invoke PhantomJS and display our spec results.

So how can we ensure that we run the specs before the build? We can create a new grunt task called build, make it default, and set it to run both the Jasmine and RequireJS tasks:

grunt.registerTask('build', ['exec:jasmine', 'requirejs']);
grunt.registerTask('default', ['build']);

By calling grunt, it will run all of these tasks for us automatically:

$ grunt

Watch for changes and run the specs

If you thought that was cool, here is a thought, "Wouldn't it be great if my specs run every time I change a file?"

Can we do that? Sure we can, and with another grunt plugin.

We are going to use grunt-contrib-watch, a plugin that watches for file changes, and runs specified tasks as a result.

First, install the plugin (Always at the project root directory.):

$ npm install grunt-contrib-watch

Next, load it in the Gruntfile:

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

And finally, set up the plugin to watch for changes on our source, spec, and lib folders, and as a result run the Jasmine task:

grunt.initConfig({
  watch: {
    scripts: {
      files: ['src/**/*.js', 'spec/**/*.js', 'lib/**/*.js'],
      tasks: ['exec:jasmine']
    }
  }
});

Now you can invoke grunt's watch task and see yours specs run each time you change any file on those directories:

$ grunt watch

Now this is development nirvana!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.97.40