Livereload magic, Gulp style!

There's been a new name making some buzz in world of JS task runners lately: Gulp. Curious, I've given it a quick go to see how hard it would be to get the minimal express & livereload setup I did with Grunt.

What's that Gulp thing

Pretty much like Grunt, Gulp allows you to define a set of tasks and run them from the command line. The most interesting point for me was the structure of the configuration file, which is more "programmatic" and less declarative. I find this makes things easier to read, but this is pretty subjective ;). Gulp is also meant to work a lot with streams doing small processings, `pipe()`-ing them to one another to create small treatment pipelines for each task. This apparently adds some performance improvements to the readability, though I have not really paid attention to that. To give a quick example, this is how a Gulp task for Javascript validation with JSHint looks like:

A bit of setup

So let's get started on this Gulp + Express + Livereload configuration. We'll split this in two steps and start with the Express setup. Then we'll add the livereload configuration.

But first of all, you'll need the gulp CLI installed on your system. A quick npm call will sort that (don't forget to sudo if your system requires it, I always do :s): npm install -g gulp.

Now the gulp command is available, let's bootstrap our project. As a starting point, we'll use a simple folder containing:

  • an index.html file (content is up to you, just make sure it has a <body>),
  • a package.json file to store the project's dependencies (npm init will help you scaffold one),
  • a local install of gulp in your project (npm install gulp from your project's folder, no -g this time),
  • a Gulpfile.js file to store Gulp configuration:

If you don't want to leave your Gulpfile empty and already start playing with Gulp, you could fill it with the following code that provides a default "Hello world"-ish Gulp task. To run your "build", just go gulp in your command line. As the command provides no specific task, it will run whatever default defines.

Express setup

To get Express to host our project's file, we'll need a new dependency in the project. Let's just npm install express --save-dev

You'll notice we're installing the actual express package and not a specific plugin for Gulp. Gulp encourages to use the libraries as is when the task has nothing to do with manipulating streams, like popping up a web server, launching tests... This makes running Express with Gulp pretty much the same as when creating a standalone Express app. This gives us the following Gulp configuration to start up Express.

The gulp command now pops up a server, and if you point your browser to http://localhost:4000, you should see the content of you index.html

The express startup could also have been a task of its own. We'd just needed to wrap it in a gulp.task call. Then we could have called it via inside the default task. It all depends on wether you need to launch express on its own or just use it when running other tasks.

Adding some livereload magic

As for starting up an Express server, starting up a livereload server doesn't have much to do with manipulating streams. This means no need for a specific Gulp plugin, we'll just use tiny-lr. We'll also need the connect-livereload middleware to inject the Javascript communicating with livereload in the pages served by Express. So let's add these dependencies:

npm install tiny-lr connect-livereload --save-dev

This makes us 3 steps away from having livereload set up. First on, starting up livereload! As with Express, we'll wrap tinylr bootstrap in a specific function (don't forget to call it in the default task ;) ).

gulp now starts up two services: Express on port 4000 and tinylr on port 35729. If you go to http://localhost:35729, you'll get a warm JSON welcome from tiny-lr.

Next step is to get express to inject the livereload JS snippet in the HTML it serves. You can skip this if you're using a browser plugin to communicate with the livereload server. This is the job of the connect-livereload middleware. We just need to load it before the the static() configuration, which makes the startExpress() function look like this:

The pages served by Express now have a small bit of JS injected just before their body closing tag. This will make them react to the livereload updates. All that's left now is sending livereload notification when file changes. Gulp comes in with a built in watch()method, so let's take advantage of this and make a final update to our Gulpfile:

What about gulp-livereload ?

If you look up on the NPM registry, you'll find a plugin for Gulp called gulp-livereload. It allows you to send notifications to the livereload server as part of your pipe() chain. This would make the notifyLivereload() function a bit more concise:

As we're not doing much with our HTML file in the current Gulpfile, this approach does not bring much besides conciseness. But when processing files more heavily, it saves you from having to watch both the source files and their processed results. You can just pipe to gulp-livereload once you've gone through, say, LESS processing and CSS minification, instead of monitoring the .less to trigger the processing, and the .css files to trigger livereload.

Wrapping it up!

Reproducing the express and livereload configuration I usually run with Grunt turned out pretty simple. I'm now really looking forward to trying out Gulp with the whole stream piping shebang to process my builds. The Gulpfile ends up maybe a bit more verbose than the Gruntfile, but I find function calls way more easy to read than lots of nested Javascript objects. But in the end, it's as personal (well, sometimes "team-personal" :p) as any other tool choices: it's just about what features it provides and how easy you find it to use.

Thanks for staying till the end! Happy Coding ;)

comments powered by Disqus