Livereloading in Gulp without a browser extension

May 15, 2017

Pre-requisites

Introduction

The fever over task-runners like Grunt, Gulp and Broccoli has largely died in 2017 due to superior alternatives such as Webpack. However, if you're like me, you're still using Gulp simply because it works for you and you're not working on big projects or in big teams to necessitate the change to Webpack.

Since initially learning about LiveReload in 2015, I have moved to Firefox (and for the most part, appreciate it). This means I do not have access to an official addon as I did on Chrome. Not only this, I neither want to install an additional extension for something I do not do 24x7 (hobby web developer), nor bloat my Firefox installation, especially if I can help it.

The problem

If you read the article on implementing LiveReload, you must have come across the following section:

Next, we need to download the Google Chrome extension LiveReload, go to the Chrome Store and download it here. Make sure you can view it in your tool bar and that the circle is filled in with black. This is important or else it won't work.

From dmitriz's gulp-automation project, which inspired me to understand his code and implement my own from scratch, you can see why he argues for a different approach:

Many of them are based on installing a Chrome browser extension. However, in addition to being limited to the Chrome browser, extensions are potentially vulnerable. Extensions can also be guilty to slow down your browser, by adding unnecessary and slow running scripts blocking your useful content. As extension runs on every page in your browser, it doesn't seem to be a good fit for the purpose of LiveReload.

Fixing our problem

For the more relevant part, let's start discussing what we are going to do to solve the problem.

Overview

Run a server on Node using Gulp

Set up base for LiveReload to use

Start listening for changes

Call LiveReload within a task re-run to request a page refresh

Run a server on Node using Gulp

We are going to use connect as a server.

npminstall --save-dev connect

Open your gulpfile.js, require connect and write a new task called server:

For now, the connect server cannot do anything. It knows to listen to port 8080 but does not know what the root of the website/app is. I'm serving a static website that outputs to build/ and so will configure it as such using the serve-static middleware for connect:

Now our connect server knows to server static files from build/ when requested over port 8080.

Set up base for LiveReload to use

We'll add connect-livereload to our project. All it literally does is inject a piece of code to your files while the connect server is running. This means that your built files will not include this piece of code.

Since it is a middleware for our connect server, we'll use it so.

Install it as usual:

npminstall --save-dev connect-livereload

Require the module in your gulpfile.js and modify the server task to make use of it.

One key thing to note is that our server task only runs after html, scss and js tasks have been run once; our watch task also runs only after server task is run. This means that the first attempt by gulp-livereload to reload the page will be futile because the LiveReload server is not yet listening for changes. This approach prevents unnecessary reloads on the first run of html, scss and js tasks.

Shortcomings

Each task requires an additional pipe with a call to gulp-livereload for my implementation to work. dmitriz's implementation works differently and does not necessitate such a behaviour.

If there are any more shortcomings in your opinion, please feel free to open an issue on the GitHub project, or submit a PR.

An alternate approach

Another approach is to use gulp.watch and livereload.changed() like so:

This will, however, reload the page before the html task finishes running. To counter this, you would have to install run-sequence and configure the order of tasks. That's yet another module we would have to add to our project. Although it would bring the entire reload logic within a single watch task, it is extensive and unnecessary in my opinion. The run-sequence project page says it is a temporary fix and such a fix should not be required with the release of Gulp 4.0. Fingers crossed.

Ruppal Singh

Front-End Web Developer

I love building beautiful static websites, complex web-apps, and taking on interesting bits in between.