The benefits of task runners in software development is obvious. They help to automate common, often tedious tasks and let you squarely focus on more important things, like writing awesome code. Seriously though, the ability to automate tasks such as image compression, minification, unit testing and much more is a huge time saver.
For many front-end developers, the goto task runner to-date has been Grunt which allowed you to define your tasks using JavaScript inside of a file called Gruntfile.js (AKA a Gruntfile). Basically, if you knew JavaScript then setting up a Grunt task was a fairly straightforward process and the breadth of third party plugins to for other tools such as JSHint, Sass and Uglify makes it one of the most flexible tools available.
For the most part, Grunt has been the task runner of choice but recently, a new one named Gulp.js has been getting a lot of attention for its ease of setup and incredibly easy configuration file format which makes it easily readable and manageable.
In this tutorial, I'll show you how to install Gulp and create a simple configuration file to get your feet wet with this great new task runner.
Installing Gulp.js
Gulp.js is a Node-based task runner just like Grunt and as such, you'll need to have Node.js installed to use it. This could be done several different ways, especially depending on your operating system. Being on OS X, I chose to use nvm, Tim Caswell's awesome script for managing multiple versions of Node.js. You can also download the binaries directly from the Node.js site. If you're totally new to Node.js, be sure to check out the Nettuts+ series on getting up-to-speed on Node.js.
Gulp.js comes packaged as a Node module making it incredibly easily to install using npm (Node Package Manager). To install Gulp, open up your terminal and type in the following:
npm install -g gulp
This pulls Gulp from the npm
registry and configures it globally on your system so you can access via command-line.
For all intents, Gulp.js is installed at this point and you're ready to start using it with your projects.
Setting Up Your Project to Use Gulp.js
To use Gulp in your project there are a couple of key things that need to be done:
- Install two dependencies packages
- Install any plugins you'd like to use
- Create a Gulp.js file to define the tasks you'd like to run
These steps need to be done inside your project's directory so that the packages and configuration files are available to Gulp.
First, lets install the dependencies:
npm install --save-dev gulp gulp-util
Now, we'll need to install the Gulp plugins that will perform the tasks that we define in our configuration file. These plugins are also Node package modules so we'll use npm
again to install them.
npm install --save-dev gulp-uglify gulp-concat
In my case, I'm installing two plugins which will allow me to minify/compress my JavaScript code using the Uglify.js compressor and concatenate all my JavaScipt files into a single source file.
Notice that I used the --save-dev
flag for install the Gulp dependencies and the plugins I'll need for my project. This ensures that an entry for each one is made to my devDependencies list inside my package.json
file like this:
{ "devDependencies": { "gulp-util": "~2.2.13", "gulp": "~3.5.0", "gulp-uglify": "~0.2.0", "gulp-concat": "~2.1.7" } }
This ensures that any package dependencies for this project can be easily installed later on using npm. If you don't have a package.json
file in your project, just type in npm init
at the command line or open a new file in your editor, include opening and closing curly braces inside and save it as "package.json". Then rerun the npm
commands listed above to update it. Note that adding the curly braces is required. Otherwise, when you try to use the --save-dev
flag, npm
will throw an error saying it's not a valid JSON file.
While I'm only using two plugins for my tutorial, Gulp offers over 200 plugins for all types of functionality including:
- LiveReload (gulp-livereload)
- JSHint (gulp-jshint)
- Sass (gulp-sass)
- CoffeeScript file compilation (gulp-coffee)
and many more.
The Gulpfile.js File
Like Grunt, Gulp has a namesake configuration file called gulpfile.js
that defines all of the required plugins along with the tasks you'll be running. You'll need to create a file called into the root of your project folder.
The syntax is straightforward and terse making it very readable and easily understandable:
var gulp = require('gulp'), gutil = require('gulp-util'), uglify = require('gulp-uglify'), concat = require('gulp-concat');
This simply tells Gulp which plugins are required to complete the defined tasks.
Next up, we need to define the tasks that will be run by Gulp. In my case, I'm looking to do two things:
- Compress images
- Minify my JavaScript files
Defining a task is for all intents a JavaScript call. We use the Gulp method task()
to define the task we want to run:
gulp.task('js', function () { gulp.src('./js/*.js') .pipe(uglify()) .pipe(concat('all.js')) .pipe(gulp.dest('./js')); });
Looking at the code above, there's a mix of method calls from the plugins I specified as required. The first method, task()
, takes a semantic name for the task (in this case ‘js') and an anonymous function which contains the real meat. Let's breakdown the code:
gulp.src('./js/*.js')
The src()
method let's me specify where to find the JavaScript files I'd like to compress and turns them into a stream representing a file structure that can be passed to the plugins for processing. This is part of Node.js' Streams API and one of the reasons for Gulp's ability to have such a terse, concise API syntax.
.pipe(uglify())
The pipe()
method takes the source stream derived from the src()
method and passes it to the specific plugin being referenced. In this example, the uglify plugin would receive the source stream.
.pipe(concat('all.js'))
Like uglify, the concat plugin receives the source stream via the pipe()
method and concatenates all JavaScript files into one file called "all.js"
.pipe(gulp.dest('./js'));
Finally, using Gulp's dest()
method, all.js
is written to my target folder. The process if very straightforward and very readable.
The last thing we need to do is update the default Gulp task to run our "js" task.
gulp.task('default', function(){ gulp.run('js'); });
By going back to the command line and typing in 'gulp'
, Gulp finds the gulpfile.js
file, loads any required plugins and dependencies, kicks off the default task and runs my 'js'
task. You can see the end result here of the minification and concatenation of my jQuery JavaScript file:
Taking this a step further, Gulp also provides another method called watch()
which provides a means for automatically checking a specific resource for changes. This allows for great automation of tasks versus constantly having to manually type in 'gulp'
at the command line.
gulp.watch('./js/*', function () { gulp.run('js'); });
When this runs, Gulp will continue to monitor the specified directly for changes to files and if a change occurs, will re-run the 'js'
task to minify and concatenate the JavaScript files. Very cool!
Shifting to Gulp.js
When I initially heard about Gulp, my first reaction was "Oh brother another tool!". Boy was I off. Gulp.js truly does have a compelling syntax and API that makes setting up your tasks a breeze. While it doesn't have the breadth of plugins that Grunt has, its plugin repository seems to be growing at a nice clip, especially now with so much developer interest.
I've already spoken with many developers that are actively migrating to it so it seems this is a great time to get into Gulp.js.
Comments