Showing posts with label Grunt. Show all posts

Speed Up Your Web Development Workflow with Grunt

I’m going to help you get started with Grunt, an open source JavaScript task runner that will help automate some of your web development tasks. Grunt will speed up and improve your build process.
My goal with this Grunt tutorial is to get you to experience the same efficiency improvements I’ve gained through this awesome task runner.

What is Grunt?

When I started my job as a front-end web developer at CDNify (we’re a content delivery network aimed at web developers, startups, and digital agencies) I had absolutely no idea what Grunt was or how it could significantly improve my development workflow.
Months down the road, and I’m now using Grunt every single day.
I can’t imagine my front-end web development workflow without it now.
In short, Grunt is an open source JavaScript project that automates repetitive tasks you often have to do as a web developer.
With Grunt, you can automate tasks like minification, unit testing, and preparing your files and website assets for production use. Grunt does this by wrapping these processes up into tasks.
A few examples of things you can automate with Grunt:
  • Optimize your web images for speed and performance
  • Analyze your code for potential errors (often referred to as linting)
  • Combine your external resources for faster page load times
  • Enforce your coding style guides for uniformity and readability throughout your project’s code base
  • Compile your CSS from your preprocessor of choice (e.g. Sass and Less)
Anything you are doing over and over again is a candidate for Grunt.
You can configure Grunt to watch certain files for changes, and then build the results on the fly.

Using Grunt in Your Web Development Team

When used in a team environment, Grunt can help every person in that team write code that adheres to the same standards/style guides. Details such as controlling the indentation of code can now be a strict process, as a whole build will fail if any part throws an error.
For example, when indenting code, you could automatically enforce the use of spaces instead of tabs (or vice versa, depending on your preferences), which will ensure that the whole team has the same configuration. When a team member pushes code to the repository, it’s in the expected format.
Grunt will help you catch sloppy code such as missing semicolons, braceless control statements, unused variables, and trailing whitespace when used in conjunction with your favorite code-quality tools (e.g. JSHint) . This is excellent for discovering human errors as well as disallowing valid — but badly written — JavaScript.

What You Need to Know

To get the most out of Grunt, you should first know (or learn about) the following.

Command-line Interface

In order to use Grunt effectively, you will need to have a basic understanding of the command prompt/terminal. At the very least, you should know how to navigate to a directory on your system and run commands on through a CLI.
If you’re not comfortable with CLIs, read this tutorial first: Getting Started with Command-Line Interfaces.
Don’t be put off; you’ll see that a CLI is very simple to use once you actually start using it. The command line is a very powerful tool. Knowing how to use it effectively can speed up your development workflow in ways beyond just being able to use Grunt. It’s a worthwhile investment to learn about CLIs.

Optional: Version Control System

Although not technically required in order to use Grunt, Grunt works best in an environment where version control is being used.
Using Grunt for a small static website that is likely to be updated infrequently may be considered overkill. Any web development project that’s larger than that should be version-controlled any ways. Large-scale websites are where Grunt becomes critical and extremely useful.
Read this list of Git tutorials for beginners or this introductory guide to Git to help you get started with Git, a popular version control system.

Get Started with Grunt

I’ll run through the general steps of installing Grunt, which is a process that relies on Node.js (an open source development platform for network applications).

Install Node.js

Node.js home page
In order to install Grunt, Node.js must first be installed or available in your dev environment, which could your personal computer or web server.
If you need help with this, read this: How to Install Node.js.
Installing Node.js allows us to install Grunt using Node.js’s package manager, called npm.

Install Grunt

Next, you need to install Grunt and its dependencies. Just run this command:
npm install -g grunt

Using Grunt in a Web Development Project

Now that you have Grunt installed, let’s go over the basics of how to use it in a web development project.
To use Grunt in a web development project, we need two files: package.json and aGruntfile (e.g. Gruntfile.js).

package.json

package.json is a JSON file. This file should be located in your project’s root directory.
Project information and settings are specified in package.json, such as the project name, version, author, and if it’s a private project or not.
package.json also contains what are known in the Node.js nomenclature as devDependenciesdevDependencies are items you need for your project. In this sense, Grunt will be an item listed under devDependencies, along with the Grunt plugins you want to use for the project (I’ll talk about this later).
Here’s an example template for a package.json file:
{
 "name" : "Project Name",
 "version" : "version number",
 "author" : "Your Name",
 "private" : true,
"devDependencies" : { "grunt" : "~0.4.0" } }
By specifying the project’s dependencies in package.json, we can use npm to install them for us automatically simply by running the following command in our project’s directory:
npm install
Running that command will give us an output like this:
npm http GET https://registry.npmjs.org/grunt
 npm http 304 https://registry.npmjs.org/grunt
 npm http GET https://registry.npmjs.org/async
 npm http GET https://registry.npmjs.org/dateformat/1.0.2-1.2.3
 npm http GET https://registry.npmjs.org/colors
 npm http GET https://registry.npmjs.org/coffee-script
 npm http GET https://registry.npmjs.org/glob
 npm http GET https://registry.npmjs.org/iconv-lite
 npm http GET https://registry.npmjs.org/findup-sync
 npm http GET https://registry.npmjs.org/lodash
 npm http GET https://registry.npmjs.org/js-yaml
 npm http GET https://registry.npmjs.org/hooker
 npm http GET https://registry.npmjs.org/minimatch
 npm http GET https://registry.npmjs.org/nopt
 npm http GET https://registry.npmjs.org/which
 npm http GET https://registry.npmjs.org/rimraf
 npm http GET https://registry.npmjs.org/underscore.string
 npm http GET https://registry.npmjs.org/eventemitter2
 npm http 304 https://registry.npmjs.org/async
 npm http 304 https://registry.npmjs.org/dateformat/1.0.2-1.2.3
 npm http GET https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz
 npm http 304 https://registry.npmjs.org/glob
 npm http 304 https://registry.npmjs.org/colors
 npm http 304 https://registry.npmjs.org/iconv-lite
 npm http 304 https://registry.npmjs.org/findup-sync
 npm http 304 https://registry.npmjs.org/lodash
 npm http 304 https://registry.npmjs.org/js-yaml
 npm http 304 https://registry.npmjs.org/hooker
 npm http 304 https://registry.npmjs.org/minimatch
 npm http 304 https://registry.npmjs.org/which
 npm http 304 https://registry.npmjs.org/rimraf
 npm http 304 https://registry.npmjs.org/underscore.string
 npm http 200 https://registry.npmjs.org/coffee-script
 npm http 304 https://registry.npmjs.org/eventemitter2
 npm http 200 https://registry.npmjs.org/nopt
 npm http 200 https://registry.npmjs.org/dateformat/-/dateformat-1.0.2-1.2.3.tgz
 npm http GET https://registry.npmjs.org/graceful-fs
 npm http GET https://registry.npmjs.org/abbrev
 npm http GET https://registry.npmjs.org/sigmund
 npm http GET https://registry.npmjs.org/lru-cache
 npm http GET https://registry.npmjs.org/graceful-fs
 npm http GET https://registry.npmjs.org/inherits
 npm http GET https://registry.npmjs.org/argparse
 npm http GET https://registry.npmjs.org/esprima
 npm http 304 https://registry.npmjs.org/graceful-fs
 npm http 304 https://registry.npmjs.org/abbrev
 npm http 304 https://registry.npmjs.org/lru-cache
 npm http 304 https://registry.npmjs.org/graceful-fs
 npm http 304 https://registry.npmjs.org/sigmund
 npm http 304 https://registry.npmjs.org/inherits
 npm http 304 https://registry.npmjs.org/argparse
 npm http 304 https://registry.npmjs.org/esprima
 npm http GET https://registry.npmjs.org/underscore
 npm http 304 https://registry.npmjs.org/underscore
 grunt@0.4.1 node_modules/grunt
 ├── which@1.0.5
 ├── dateformat@1.0.2-1.2.3
 ├── colors@0.6.0-1
 ├── hooker@0.2.3
 ├── async@0.1.22
 ├── eventemitter2@0.4.12
 ├── coffee-script@1.3.3
 ├── underscore.string@2.2.1
 ├── iconv-lite@0.2.11
 ├── lodash@0.9.2
 ├── findup-sync@0.1.2 (lodash@1.0.1)
 ├── rimraf@2.0.3 (graceful-fs@1.1.14)
 ├── nopt@1.0.10 (abbrev@1.0.4)
 ├── minimatch@0.2.12 (sigmund@1.0.0, lru-cache@2.3.0)
 ├── glob@3.1.21 (inherits@1.0.0, graceful-fs@1.2.3)
 └── js-yaml@2.0.5 (esprima@1.0.3, argparse@0.1.15)

Gruntfile

The Gruntfile is the main configuration file for the project, and specifies what tasks Grunt should run and what files in the project they affect.
Your project’s Gruntfile can be a JavaScript file (Gruntfile.js) or CoffeeScript file (Gruntfile.coffee).
In this tutorial, we’ll be using JavaScript.
At its most basic form, the Gruntfile should contain the following:
module.exports = function(grunt){
 grunt.initConfig({
  pkg: grunt.file.readJSON('package.json')
 });
 
 grunt.registerTask('default', []);
};
initConfig is where the dependency options are specified. Each Grunt plugin is configured using a JSON object (with some exceptions).
Some plugins allow more than one configuration to be loaded. For example, there may be a specific set of experimental JavaScript that uses a different library to jQuery, and so that library must be predefined instead of jQuery in the JSHint configuration. (We will look at this in more detail in the third part of this Grunt tutorial series.)
registerTask can be specified more than once. The default task is run when Grunt is executed in the command line, and so this should contain common setup tasks.
At this point, if you run Grunt successfully, it will generate the following output:
Done, without errors.
Now we have a project skeleton which will become useful once we use some plugins.

Using Grunt Plugins

A key feature of Grunt is the use of Grunt plugins. Grunt plugins are referred to asgruntplugins in the Grunt nomenclature.
gruntplugins are user-contributed modules that will help you automate tasks without having to write your own task scripts.
For example, you can use the grunt-contrib-compress gruntplugin to compress and optimize the file sizes of your project files.
To use the plugin in a project, these are the steps to take:
  1. List it as a devDependency object in package.json
  2. Load it using the loadNpmTasks function in the project’s Gruntfile
  3. Register the task by using the registerTask function in the project’s Gruntfile
  4. Run npm install to install Grunt and the plugin
Here’s the sample source code for using the grunt-contrib-compress gruntplugin in your project.
package.json
{
 "name" : "My Sample Project",
 "version" : "1.0",
 "author" : " Ben Briggs",
 "private" : true,

 "devDependencies" : {
  "grunt" : "~0.4.0",
  "grunt-contrib-compress" : "~0.5.2"
 }
}
Gruntfile
module.exports = function(grunt){
 grunt.initConfig({
  pkg: grunt.file.readJSON('package.json')
 });

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

 grunt.registerTask('default', [compress]);
};
Grunt plugins are actually just npm modules that follow the gruntplugin template. You can find gruntplugins on the npm registry by browsing modules tagged with "gruntplugin" or at the official Grunt Plugins page. There are currently over 300 listed gruntplugins.

Grunt vs Gulp: Which One Should You Use?

Nobody likes doing boring and repetitive tasks. The good news is we can probably make our computer do them for us.
When it comes to web development build automation, there are two major players you will want to look at: Grunt and Gulp.
But, which one should you go with? What are the differences between them? Which one is better?
Let’s take a look at the similarities and differences between Grunt and Gulp in order to help you choose the right JavaScript task runner for you.
Grunt vs. Gulp

Similarities between Grunt and Gulp

Grunt and Gulp can automate tedious, human-error-prone build processes such as:
  • code minification
  • code-quality analysis
  • image optimization
  • vendor-prefixing
  • unit-testing
  • … and much more
Basically, if you’re doing something over and over again, there’s a huge chance that you can automate it using either Grunt or Gulp.
By integrating a task runner into our workflow, we avoid wasting time and energy on things our computer can do for us. Ultimately, this means we will be able to focus on stuff that matter most: Creation and innovation.
Think of a task runner as a framework for automating development tasks.
JavaScript web development frameworks like Angular and jQuery make it easier to write JavaScript code. Likewise, Grunt and Gulp make it easier to write build-automation code.
How does a task runner work? Simple. You write instructions that tell the task runner:
  1. which files you want it to process
  2. what you want it to do with the files (minify them, analyze them for errors, etc.)
  3. where you want it to place the processed files
Since Grunt and Gulp are JavaScript task runners, we write our instructions using JavaScript.
Here are step-by-step tutorials that will help you get started with Grunt and Gulp:
At first glance, Grunt and Gulp both seem quite alike.
And using either one of them leads to the same result: A more efficient web development workflow.
So, in the broader sense, Grunt and Gulp are identical in that:
  • They’re task runners that can automate portions of our development workflow
  • We write the tasks we want them to run using JavaScript
  • They both need Node and npm in order to work
The similarities end there. The way they are configured and their method for executing our tasks are different.

Differences between Grunt and Gulp

There are two main differences between Grunt and Gulp:
  • The way you configure your tasks. Grunt is configuration-based. Gulp is stream-based.
  • The way they run your tasks. Grunt runs the processes you want to execute in a sequential manner. Gulp tries to run them with maximum concurrency, meaning it will try to execute processes in parallel if possible.

Task Configuration

Let’s explore a major difference between Grunt and Gulp by way of an example.
We will create a task for Grunt and Gulp to do. This task will take a bunch of CSS files and optimize them to improve web performance.
Here is what the task will do:
  1. Combine all CSS files found inside the src directory into one big stylesheet
  2. Minify the stylesheet
  3. Placed the minified file into the css directory with the name ofstyles.min.css
  4. Report the task-execution time in the command line after the task has completed

Grunt Task Configuration

module.exports = function(grunt) {
  // Report the task-execution time in the command line
  require('time-grunt')(grunt);
  // Task configuration
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    // Combine all CSS files found inside the src directory
    concat_css: {
      dist: {
        src: ['src/*.css'],
        dest: 'css/styles.css'
      }
    },
    // Minify the stylesheet
    cssmin: {
      target: {
        // Write the minified file in the css directory
        files: [{
          'css/styles.min.css': ['css/styles.css']
        }]
      }
    }
  });
  // Load the plugins
  grunt.loadNpmTasks('grunt-concat-css');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  // Use `grunt` command to run the task
  grunt.registerTask('default', ['concat_css', 'cssmin']);
}

Gulp Task Configuration

// Load the plugins
var gulp = require('gulp');
var concatenate = require('gulp-concat-css');
var minify = require('gulp-cssmin');
var duration = require('gulp-duration');
// Task configuration
gulp.task('default', function() {
  gulp.src('src/*.css')
  // Combine all CSS files found inside the src directory
  .pipe(concatenate('styles.min.css'))
  // Minify the stylesheet
  .pipe(minify())
  // Report the task-execution time in the command line
  .pipe(duration('Execution Time: '))
  // Write the minified file in the css directory
  .pipe(gulp.dest('css/'));
});
// Use `gulp` command to run the task

Task Configuration Difference

Gulp’s syntax is terser. The great thing about Gulp is the stream-based build system. You just create your tasks by piping in all of your processes, one after another. Sort of like how we can chain methods on the selector function in jQuery.
The magic happens because of the object format that plugins exchange, the so called Vinyl. Vinyl is just an abstraction that describes a virtual file object—one that could refer to an existing file on the FS, a stream, or simply dead-ends with a null.
— Preslav Rachev
What I have found was most of the tasks I create with Gulp result in a much shorter and cleaner task configuration file. In other words, with Gulp, there is less code to write for doing the same processes.
You may think I’m biased — maybe a little — but I do use both Grunt and Gulp. (I choose one over another depending on the type of project I’m working on.)
The following table lists the Grunt and Gulp plugins used in the task.
ProcessGrunt PluginGulp Plugin
concatenationgrunt-concat-cssgulp-concat-css
minificationgrunt-contrib-cssmingulp-cssmin
Display task-execution speed in the command linetime-gruntgulp-duration

Task Execution

The manner in which a task is executed is different in Grunt vs. Gulp.

How Grunt Executes a Task

For each process in a task, Grunt needs to:
  1. Open the processed file from the last process
  2. Run the current process
  3. Save the changes
  4. Close the current processed file so that the next process can access it

How Gulp Executes a Task

Gulp, on the other hand, doesn’t need the intermediary steps of creating temporary files in between processes.
The code that comes out of a process goes directly into the next one, saving a lot of I/O time. That’s why it’s “stream-based”.
Gulp uses Orchestrator, which helps it run processes with maximum concurrency. This means Gulp will try to perform processes simultaneously. Theoretically, this allows Gulp to finish tasks faster.

Measuring Task-Execution Speed

You can test the speed difference between Grunt and Gulp. They can both report the time it takes to complete tasks.
To measure the execution speed of the tasks we created earlier, the time-grunt and gulp-duration plugins were used.
The Grunt task and the Gulp task were executed five times each.
The same source files were used (three CSS files).
The destination directory (i.e. the css directory) was removed from the machine in between each task execution. This way, the task runners are required to write to disk each time the task was executed.
Be careful when interpreting the results of the following data. Many factors can affect the results, such as the variances between the Grunt and Gulp plugins for concatenating, minifying, and reporting execution speed.
Grunt Task-Execution Speeds
Test 1915ms
Test 2941ms
Test 3908ms
Test 4994ms
Test 5938ms
Average Time939.2ms
Gulp Task-Execution Speeds
Test 1229ms
Test 2229ms
Test 3226ms
Test 4225ms
Test 5221ms
Average Time226ms
In this particular case, Gulp was able to execute the CSS optimization task 4x faster than Grunt.
For simple tasks, you’ll never notice the difference. But for complex build-automation tasks that take minutes to complete, this might be an issue. You don’t want to wait around longer than you have to.
It’s worth pointing out that there is a new version of Grunt on the way. It will use Orchestrator too. This will most likely lead to task-execution speed improvements.
Check out this blog post where Zander Martineau made a speed comparison test of Grunt vs. Gulp. He similarly reports that Gulp was able to complete tasks quicker than Grunt.
Source: tech.tmw.co.uk

Grunt vs Gulp Stats

Project Start Date

The Grunt project started in late-2011. It took the project about a year to get noticed. Since it was the first to arrive in the market, it has a larger user-base compared to Gulp.
Gulp entered the scene in mid-2013. It only got noticed in the beginning of 2014. Since then, the number of adopters have been ramping up.

Usage

To get an idea of how many developers use Grunt and Gulp, we can look at the npm download stats for the grunt and gulp packages.
Since downloading the grunt and/or gulp package is the first step to using the task runners, this is a decent starting point for attempting to quantify how many people use Grunt and Gulp.
However, the “download” metric has several flaws for comparative purposes. Some developers might be using both Grunt and Gulp. Gulp has released more version updates compared Grunt, and the might lead to increased download rates due to people updating their software. This measurement only tells part of the story.
The following data is from npm-stat — a tool that reports statistics about npm packages.

Grunt Usage Stats

Total downloads14 million
Number of downloads last month1.3 million
Average number of downloads per day42,075

Gulp Usage Stats

Total downloads5.9 million
Number of downloads last month~929,000
Average number of downloads per day32,479

Amount of Plugins

Plugins are the bread-and-butter of task-configuration. Although you can certainly write your own processes to automate, it’s much easier to use a pre-existing one if it already exists.
Both Grunt and Gulp have official plugin directories on their site.They both display the number of plugins listed in their respective plugin directories.
Grunt has 4,663 plugins.
Gulp has 1,561 plugins.
Clearly, Grunt has more plugins than Gulp, with nearly 3x more plugins compared to its the latter. Keep in mind that Grunt has a bit of a head start, so having more plugins is to be expected.

Development Activity

When relying on a piece of software, it’s a good idea to look at how frequently it gets updated.
You want to use tools that are being quickly and continually improved via bug fixes, patches for security vulnerabilities, and feature enhancements.
By looking at the GitHub repositories of Grunt and Gulp, we can gain insights about the level of development activity these two open source projects have. That’s because GitHub displays the number of commits, releases, and contributors.
Commits occur whenever the source code has been updated. This can be a good signifier of how active the developers of the project are when it comes to fixing bugs and adding/improving features.
In software, releases refer to distinct stages of development. For example (using semantic versioning conventions) v1.0.0 is the first stable release. v2.1.2 is a more mature release. The number of releases can show how often the software is updated. It can give us a clue on how responsive the project’s developers are when vulnerabilities and other issues are found.
Contributors are the hard-working people who contribute code to the project. More GitHub users contributing to the project can mean that there are more people reviewing the project’s source code, more people that can help develop the project, and a greater chance that someone can/will take over if the creators of the project decide they no longer wish to work on the project.
The tricky thing about using these metrics to measure software development activity is that each project may have unique policies for committing source code and releasing updates. Also, they may have certain requirements and guidelines that affect the number of people contributing code to the project. Also, as open source projects mature, there will naturally be fewer bugs to fix and features to add. So, theoretically, the rate of commits and releases will decrease as the project gets older.
But at least we can use these numbers to get a rough feel for how often the developers of Grunt and Gulp update their respective repos.

Grunt Development Activity Stats

Commits1,310
Releases8
Contributors54

Gulp Development Activity Stats

Commits814
Releases14
Contributors135
The good news is both Grunt and Gulp are healthy in terms of development activity.
At the time of writing, Grunt had a commit five days ago, while Gulp had one four days ago.
Grunt’s lastest release was close to 11 months ago. Gulp’s last release is more recent, about  3 months ago.
Where they differ most is in the number of developers contributing to the project.Gulp has 2.5x more developers working on the project.

Popularity

In GitHub, you can quantify the amount of people who are interested in a repository by looking at the Watch, Star, and Fork metrics.
The Watch metric is the number of GitHub users actively monitoring the activities in a repo.
The Star metric is the number of GitHub users who have “favorited” the repository.
The Fork metric shows the number of GitHub users who have copied the project to their own GitHub account.
These metrics can give us insights about the popularity of a project on GitHub.

Grunt Popularity Stats

Watchers563
Stars9,466
Fork1,120

Gulp Popularity Stats

Watchers653
Stars13,540
Fork1,240
Even though Grunt is older than Gulp, we can see just by the number of stars, watchers, and forks that Gulp is more popular right now.

Data Sources

Stats were obtained on May 11, 2015. The average number of downloads per day were calculated based on stats from May 1-7, 2015.
Sources:

Conclusion

So, should you use Grunt or Gulp?
Honestly, that’s up to you. It’s tough to say.
One isn’t better than the other. They’re the same type of tool that can do the same job. So it will come down to personal preferences.
But let me share with you how I use Grunt and Gulp, in case you are wondering, and also to illustrate that you don’t have to pledge your allegiance to just one of them.
I use Grunt for my Angular projects. Mainly because of the Yeoman generator for AngularJS plugin that scaffolds my app just the way I like. There’s also a Gulp version for this, generator-gulp-angular, but I didn’t like it. So I keep using Grunt for Angular projects. I make some small tweaks and updates on my task configurations if needed.
I mainly use Gulp for my Laravel projects and some small websites. Basically, if I can’t find a Yeoman generator that suits me, I’ll make it from scratch using Gulp. Gulp, in my opinion, is much simpler to use and configure.
Hopefully the information you have read here will help you decide between Grunt or Gulp.