I am trying to setup my gulpfile.js
to use livereload on an express server without much luck. I see examples out there but they seem to be related to a static file server.
http://code.tutsplus.com/tutorials/gulp-as-a-development-web-server--cms-20903
http://rhumaric.com/2014/01/livereload-magic-gulp-style/
So I have an app.js
file which does the standard express server with jade files, etc. What I want to do is get it to work with livereload from a gulp.js boot.
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
There are lots of plugins like gulp-livereload
, connect-livereload
, gulp-connect
, gulp-watch
so how can I get this wired up?
I've added code that
Detects changes in server files and reloads the server via nodemon
Waits for a couple seconds after process reload in order to give the server time to run its initialization code.
Triggers a change in a livereload server
note 1 : Your build should also include a livereload server and attach livereload scripts to html files before calling the 'serve' task
note 2: This is an asynchronous task that never ends, do not use it as a dependency of other tasks
gulp.task('serve', function (cb) {
nodemon({
script : <server start file>,
watch : <server files>
//...add nodeArgs: ['--debug=5858'] to debug
//..or nodeArgs: ['--debug-brk=5858'] to debug at server start
}).on('start', function () {
setTimeout(function () {
livereload.changed();
}, 2000); // wait for the server to finish loading before restarting the browsers
});
});
Here's my solution:
//gulpfile.js:
var gulp = require('gulp');
var nodemon = require('gulp-nodemon');
var server = require('gulp-express');
var lr = require('tiny-lr')();
gulp.task('default', function () {
nodemon({
script: 'server.js'
})
.on('restart', function () {
console.log('restarted!')
});
lr.listen(35729);
gulp.watch('server/**/*', function(event) {
var fileName = require('path').relative('3000', event.path);
lr.changed({
body: {
files: [fileName]
}
});
});
});
You also need to include connect-livereload in your express server:
app.use(require('connect-livereload')());
Include it before bodyParser. I have read that this is not needed if you have the chrome live reload extension.
gulp-express is the right thing for you. It runs your express script as a server, with livereload!
I had the same issue and was not able to find anything related. My solution ends up with the following piece of code in Gulpfile
:
var fork = require('child_process').fork;
var tinyLr = require('tiny-lr');
var async = require('async');
var plugins = require('gulp-load-plugins')({ lazy: false });
var lr = null;
var lrPort = 35729;
var buildDir = 'build';
var serverAppFile = path.join(__dirname, 'build/server/app.js');
// This guy starts and stops nodejs process which runs our Express app
var app = {
start: function(callback) {
process.execArgv.push('--debug');
var instance = app.instance = fork(serverAppFile, {
silent: true
});
app.dataListener = function(data) {
var message = '' + data;
// Assume that server is started when it prints the following to stdout
if (message.indexOf('Express server listening on port') === 0) {
callback();
}
};
instance.stdout.on('data', app.dataListener);
instance.stdout.pipe(process.stdout);
instance.stderr.pipe(process.stderr);
},
stop: function(callback) {
app.instance.stdout.removeListener('data', app.dataListener);
plugins.util.log('Killing Express server with PID', app.instance.pid);
app.instance.kill('SIGTERM');
callback();
}
};
// build-assets task actually processes my client js, less, images, etc and puts them to build dir
// build-server task copies server files (app.js, controllers, views) to build dir
gulp.task('serve', ['build-assets', 'build-server'], function(callback) {
async.series([
app.start,
function(callback) {
lr = tinyLr();
lr.listen(lrPort, callback);
}
], callback);
});
gulp.task('watch', ['serve'], function() {
// Reload page if built files were updated
gulp.watch([
buildDir + '/**/*.handlebars',
buildDir + '/**/*.html',
buildDir + '/**/*.js',
buildDir + '/**/*.css'
], function(event) {
var fileName = path.relative(path.join(__dirname, buildDir), event.path);
plugins.util.log('Detected updated file ' + fileName + ', reloading server and page in browser');
async.series([
// Restart Express server
app.stop,
app.start,
// Send reload notification to browser
function(callback) {
lr.changed({
body: {
files: [fileName]
}
});
callback();
}
]);
});
// Perform build steps on source file modifications
gulp.watch(['app/**/*.js', '!app/**/*.spec.js'], ['build-app-js']);
gulp.watch(['app/**/*.html'], ['build-templates']);
gulp.watch(['app/**/*.less'], ['build-less']);
gulp.watch(['server/**/*.*'], ['build-server']);
});
You'll need to install tiny-lr
, async
, gulp-util
and gulp-load-plugins
packages for this sample to work.
I guess that I'll create a separate Gulp plugin for it =)
Take a look at gulp-nodemon which will restart your server when code changes.
Example:
gulp.task('develop', function () {
nodemon({ script: 'app.js', ext: 'html js' })
.on('restart', function () {
console.log('restarted!')
})
})
Live reload should work with any nodejs script. Here is a good gist.
You can see the setup I used at http://github.com/arvsr1988/gulp-expressjs-setup