LiveReload with BrowserSync and Gulp

In my previous blog post, I have written about how to use LiveReload Chrome extension, with Guard and some Ruby gems to make a web page automatically reload in a browser, Chrome browser to be specific. Just by reading this sentence, it already sounds like a complicated task. And indeed it is. Luckily, I have found a better solution: BrowserSync.

With LiveReload, you have to install browser extension, but BrowserSync uses Socket.io, so it can supports more than one browser at once. This is great for working with responsive design, where screens with different sizes are needed to be tested.

No need to install extension and support more than one browser are really big plus.

The following is a short instruction and some examples on how to use both BrowserSync and Gulp to automatically reload a web documentation page generated by Docco in any connected browser.

Install necessary modules as dependencies in package.json:

1
$ npm install --save-dev gulp gulp-docco browser-sync

Update gulpfile.json to include a BrowserSync task:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var gulp = require('gulp');
var browserSync = require('browser-sync');
var docco = require('gulp-docco');
// Generate documentation pages and save into `docs` directory.
gulp.task('docs', function () {
return gulp.src([*.js'])
.pipe(docco())
.pipe(gulp.dest('docs'));
});
gulp.task('browser-sync', function () {
// Docco generated files will be saved in the `docs` directory
browserSync({ server: { baseDir: './docs' }, open: false });
});
gulp.task('default', ['browser-sync'], function () {
gulp.watch(['*.js'], ['docs', browserSync.reload]);
});

The default task depends on task browser-sync. It is necessary to first run the server before any livereload can happen.

To run the (default) task:

1
2
3
$ gulp
...
[BS] Reloading Browsers...

When changes were made to any of .js file, it will first generate latest documentation in docs directory, and then BrowserSync will automatically reload the browser.

Reload is not just happening to one browser, but all connected browsers, this is done via Socket.io. This is great for cross browser testing:

When you’re making responsive websites, there’s a lot of tweaking and testing to do. BrowserSync makes your workflow faster by synchronising URLs, interactions and code changes across multiple devices. - http://www.browsersync.io/

But there is a quirk, browserSync.reload must be the last task in the watch array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// This is an async task that will run after `task-2`.
gulp.task('task-1', function (cb) {
setTimeout(function () {
console.log('task-1');
cb();
}, 2000);
});
// This task will run before `task-1`.
gulp.task('task-2', function () {
console.log('task-2');
});
gulp.task('default', ['browser-sync'], function () {
// Watched tasks are run in parallel, not in series.
gulp.watch(['*.js'], ['task-1', 'task-2', browserSync.reload]);
});

When the task executes:

1
2
3
4
5
6
7
8
9
[14:49:24] Starting 'task-1'...
[14:49:24] Starting 'task-2'...
task-2
[14:49:24] Finished 'task-2' after 15 μs
[14:49:24] Starting 'docs'...
[14:49:24] Finished 'docs' after 58 ms
task-1
14:49:26] Finished 'task-1' after 2 s
[BS] Reloading Browsers...

From the log above, you can see that task #1 started earlier than task #2, but finished later. But BrowserSync reload happens after all previous tasks. Gulp is yet to support running tasks in series. But with browserSync.reload, it always runs at last.

If changing the line with watched tasks to:

1
gulp.watch(['*.js'], ['task-1', browserSync.reload, 'task-2']);

An error will be thrown:

1
Error: pass strings or arrays of strings

Make sure browserSync.reload is the last task in the list.

So, no additional extension to plug, no gems to mine, and no complex setup task, just npm install.

Tools should be easy to use!