Benefits of Grunt
Many people are of the opinion that the benefit of using Grunt (or any build tool for that matter) is to possibly save time, and often this tradeoff—of learning time versus actual development time is deemed too risky, which then leads to the programmer staying safe with the manual method. This perception is misguided. The added efficiency is only one of benefits of using Grunt, the other main benefits include: build consistency, increased effectiveness, community utilization, and task flexibility.
Efficiency
Hypothetically, let's say it takes us 2 minutes per build and we need to build (and run the tests) numerous times every hour, resulting in approximately 50 builds per day. With this schedule, it costs us approximately 100 minutes per day in order to perform the monotonous task of manual running various sets of command-line tools in the right sequence. Now, if learning a new build tool like Grunt takes us 2-3 hours of research and 1-2 hours to implement the existing build process as a Grunt build, then this cost will be recovered in only a week of work. Considering that most programmers will be using their trade for years to come, the decision is simple—use a build tool as it is well worth the time investment.
With this in mind, we can see the time spent to learn a new tool like Grunt is negligible in comparison with the time saved across the entire span of all projects in which that tool is used.
Consistency
The human propensity for error is an unavoidable hurdle programmers face when carrying out a manual build process. This propensity is further increased if a given build process involves each command being manually typed out instead of saving them in some kind of script for easier execution. Even with an array of scripts, problems can still arise if someone forgets to execute one, or if the special script required for a special situation is forgotten.
Using Grunt provides us with the ability to implement our build logic inside the build process. Once the build has been set up and confirmed, this effectively removes the possibility for human error from the equation entirely. This ability also helps newcomers contribute to your projects by allowing them to quickly get started on the code base as opposed to getting bogged down trying to understand the build.
Also, as a result of the great effort behind the Node.js project, we can also run our encapsulated build process across all major operating systems. This allows developers from all walks of life to use and enhance a common build process.
Effectiveness
As well as saving time from doing less, we also save time by staying in the zone. For many programmers, it often takes us some time to gather momentum in order to bring our brains into gear. By automating the build process, we multi-task less, allowing us to keep our minds focused on the current task at hand.
Community
A common problem for many build tools is the lack of community support. Most build tool have plugins for many common build processes, but as soon as we want to perform a task that is too niche or too advanced, we are likely to be forced to restart from scratch.
At the time of writing, npm (the Node.js Package Manager) contained approximately 50,000 modules and, as mentioned above, approximately 1,900 of these are Grunt plugins. These plugins cover a wide array of build problems and are available now via the public npm repository, which provides a purposefully simple means to publish new modules to the repository. As a result of this simplicity, anyone may share their Grunt plugin with the rest of the world with a single npm publish
command. This concept makes it easy for programmers of every skill level to share their work. Allowing everyone to build upon everyone else's work creates a synergistic community, where the more people contribute, the more valuable the community becomes, which in turn provides further incentive for people to contribute. So, by using Grunt, we tap into the power of the Node.js community. This fact alone should be enough to convince us to use Grunt.
GitHub (http://gswg.io#github) is another valuable community tool that greatly benefits Grunt. As of June 2013, JavaScript code makes up 21 percent of code on GitHub making it the most popular programming language on GitHub. However, this fact alone is not the only reason to host your project on GitHub. The Git (http://gswg.io#git) Distributed Version Control System (DVCS) provides the ability to branch and merge code, and the flexibility of both local and remote repositories. This makes it the superior choice for open-source collaboration, compared to other (non-distributed) VCS tools such as SVN or TFS.
With the combination of GitHub (being a great JavaScript open-source collaboration platform) and npm (being so widespread and simple to use) the Grunt team provides Grunt users with the perfect environment for an open-source community to thrive.
We'll cover more on npm in the Chapter 2, Setting Up Grunt and contributing to open-source projects in Chapter 5, Advanced Grunt.
Flexibility
Another common problem for many build tools is the level of prior knowledge required to write your own task. Often, they also require varying levels of setup before you can start actually writing code. A Grunt task is essentially just a JavaScript function, and that's it. Tasks can be defined with various levels of complexity to suit the needs of build process. However, remaining at the root of all tasks is the idea of one task being one function—for example, this Gruntfile.js
defines a simple task called foo
:
//Code example 02-simple-task module.exports = function(grunt) { grunt.registerTask('foo', function() { grunt.log.writeln('foo is running...'); }); };
Our new foo
task is runnable with the command: grunt foo
. When executed, we see:
$ grunt foo Running "foo" task foo is running...
We'll learn more about Grunt tasks in Chapter 3, Using Grunt.
The arguments for using various build tools generally stem from two conflicting sides: the simplicity of configuration or the power of scripting. With Grunt however, we get the best of both worlds. We are able to easily create arbitrary tasks as well as define verbose configuration. The following Gruntfile.js
file demonstrates this:
//Code example 03-simple-config module.exports = function(grunt) { grunt.initConfig({ bar: { foo: 42 } }); grunt.registerTask('bar', function() { var bar = grunt.config.get('bar'); var bazz = bar.foo + 7; grunt.log.writeln("Bazz is " + bazz); }); };
In this example, we are first initializing the configuration with an object. Then, we are registering a simple task, which uses this configuration. Note, instead of using grunt.initConfig(…)
in the preceding code, we could also use grunt.config.set('bar', { foo: 42 });
to achieve the same result.
When we run this example with grunt bar
, we should see:
$ grunt bar Running "bar" task Bazz is 49
This example demonstrates the creation of a simple task using minimal configuration. Imagine we have created a task which parses JavaScript source code into a tree of syntax nodes, traverses these nodes, performing arbitrary transforms on them (like shortening variable names) and writes them back out to a file, with the ultimate effect of compressing our source code. This is exactly what the UglifyJS
library does, with many configuration options to customize its operation. We'll cover more on JavaScript Minification in the next section.