Task Runners pt.3: Gulp
Last time, we covered how to install, configure, and use Grunt to automate some common web optimization tasks to aid our development workflow. There was a lot to cover and I'm about to segue to a different tool (which performs the same function), which has a couple specific gains beyond some other niceties; I'll get to those in a bit. For now, hang on and enjoy the ride.
Why Use Gulp
So, you may be wondering, why use gulp as opposed to Grunt? Honestly, if you're familiar with one already, go with what you know; they're both rather awesome and gulp, while newer, is gaining popularity enough to rival Grunt in its presence. As for the specifics, gulp set out to "right some of the wrongs" of Grunt. This isn't to say Grunt has anything wrong with it, but Grunt generally uses a certain verbosity in plugin loading and configuration defintions. While Grunt's task configurations are callback function/object heavy, gulp adds functionality in pipelines.
Gulp makes use of Node streams. If you want to dig into why this is important for how gulp handles tasks, be my guest. I can also tell you that Grunt has many more plugins they've built and maintained in their core (the
grunt-contrib-... packages) and gulp has taken a different approach. So, what's the big draw?
Gulp made it easier for me to load my
json-server instance and continue interacting and building via my other tasks with browser-sync integration. This certainly has much to do with the specific json-server plugin I'm using, but as my efforts with those in Grunt were (for the time being) futile, I'm good with moving on.
For me, it's come down to three primary reasons:
- I can make my
json-serverinstance behave nicely, for a single Terminal/CLI instance
- I like the syntax of the gulpfile.js better
- it's flipping fast
Gulp advertises that they want to help you "automate and enhance your workflow", which I believe both Grunt and gulp do, but gulp certainly has caught my attention.
Like Grunt, gulp is Node-based and installable via npm. You can install it (globally) with
npm install -g gulp; to install it into a project (as a development dependency, which you should do), we drop the global flag and add the save-dev flag, as such
npm install gulp --save-dev. The latter will save it into the
package.json which ensures that any cloning of the repository will easily ensure its availability, with any dependencies, via
Gulpfile Basic Structure and Example
As before, I'll focus mostly on the jshint plugin for demonstrative purposes, then I'll combine things at the end to compare my
Gruntfile.js and my
Here's a barebones followed by a basic implementation.
var gulp = require('gulp'); gulp.task('default', ['someTask', 'anotherTask']);
That level of simplicity after the
Gruntfile.js business was something I found quite refreshing (sorry, I had to work it in somehow). To get started with gulp and jshint, we need to install jshint to be available as a plugin, again via npm with
npm install gulp-jshint --save-dev. My basic example includes gulp-util, which is an excellent package to help with interacting with plugins and the console's output; you'll need to either install that with
npm install gulp-util --save-dev or ignore it (and remove its corresponding require line).
Here, as you can see, even with defining my 'default', 'jshint', and 'watch' tasks, things are kept fairly simple. The file only truly loads any dependencies and registers tasks; that's it. I hope you're catching on to why I prefer gulpfile syntax.
As shown with Grunt, we can invoke a specific task or run the default without arguments. For example
gulp will runn all specified tasks for 'default' versus
gulp jshint will only run the 'jshint' task.
Here's the expanded example, with the same 'jshint', 'watch', and 'browser-reload' tasks. It also has my
json-server implementation, since my Grunt implementation had me running it as a background task. We again need to install the additional dependent packages of 'gulp-json-srv' and 'browser-sync' (if that isn't already installed from the last post). Again, these packages are listed in the
package.json I provided in the first post, so if you have run
npm install, you'll pick up on them.
Comparing Gulp and Grunt
Here's an example of my 'jshint' task running in both Grunt and gulp. As you can see, there's not a lot of difference at this granular level. I believe this is a credit to both implementations.
Note: I took the default formatting for jshint in both Grunt and gulp, which is why they look so different. I can template the output differently, but didn't for brevity.
Where this is all headed is something I'll get into soon. To round out the picture, I want to:
- check my client-side code (jshint)
- uglify/minify and join (concatenate) my front-end JS assets (vendor libraries then custom app content)
- minify and join (concatenate) my CSS files
- minify / collapse white space on HTML files
- document my code
provide the the above as the "build" of my app to the published application
- keeping the "source" separate from the production app
- after having tested the app to make sure it didn't break on its way to production
Where there are gaps, there will be more coming soon.
You may have noticed, if you've familiarized yourself with my MWLUG slide deck (or had the benefit of attending my session) that many of the same themes about delivering optimized content were core to what I was demonstrating with my Nginx + PageSpeed reverse proxy. While a reverse proxy can add this functionality after-the-fact (which is a very powerful baseline), it doesn't solve the fact that the reason for these optimizations is to reduce runtime execution. Pre-building your content is the best way to ensure that your users will load their optimized content.
If you're looking to read up more on these tasks, I recommend checking out the scotch.io tutorial "A Simple Guide to Getting Started With Grunt" and their equivalent "Automate Your Tasks Easily with Gulp.js" tutorial. Egghead.io has some videos, including a couple free ones, on using Grunt. HTML5rocks.com also has a tutorial on "Supercharging your Gruntfile" or if you're having trouble with the concepts outlined here, check out "Grunt for People Who Think Things Like Grunt are Weird and Hard".
To Be Continued...
...in part 4.