15

I have written an application in Node.js (with Express & socket.io) and I would like to use Grunt to compile my client-side stuff with livereload while developing and being connected to Node.js application. How can I do this? (Preferably without running Node.js app in another port and client in another port, because of pathing and cross-domain issues)

I installed also Yeoman and it's using out of the box grunt-contrib-livereload package, but from what I understood it's using Node.js Connect server for serving client-side files, thus being separated from my Node.js application..

Example from Gruntfile.js generated by Yeoman:

var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

// ... cut some parts
grunt.initConfig({
    watch: {
        livereload: {
            files: [
                '<%= yeoman.app %>/*/*.html',
                '{.tmp,<%= yeoman.app %>}/styles/*.css',
                '{.tmp,<%= yeoman.app %>}/scripts/*.js',
                '<%= yeoman.app %>/images/*.{png,jpg,jpeg}'
            ],
            tasks: ['livereload']
        }
        // ..cut some parts
    },
    connect: {
        livereload: {
            options: {
                port: 9000,
                middleware: function (connect) {
                    return [
                        lrSnippet,
                        mountFolder(connect, '.tmp'),
                        mountFolder(connect, 'app')
                    ];
                }
            }
        }
    }
    // ..cut some parts
});

grunt.registerTask('server', [
    'clean:server',
    'coffee:dist',
    'compass:server',
    'livereload-start',
    'connect:livereload',
    'open',
    'watch'
]);
acoder
  • 513
  • 2
  • 5
  • 8

3 Answers3

7

Not sure if you have solved this question yet, but I have done this by adding my express application as a middleware attached to the 'connect.livereload.options.middleware' option.

However, automatic reloading of server side code doesn't work. For that you could implement a reload friendly server using a simple 'node ./server.js', create a connect middleware that acts as a transparent proxy to your development server, and invoke that within your Gruntfile.js before your standard connect/livereload server starts.

connect: {
    options: {
        port: 9000,
        // change this to '0.0.0.0' to access the server from outside
        hostname: 'localhost'
    },
    livereload: {
        options: {
            middleware: function (connect) {
                return [
                    lrSnippet,
                    mountFolder(connect, '.tmp'),
                    mountFolder(connect, 'app'),
                    require('./server') // your server packaged as a nodejs module
                ];
            }
        }
    }
}

server.js:

var app = express();

...
// Export your server object.
module.exports = app;
Sheena Artrip
  • 1,990
  • 12
  • 16
  • Do you set up your server in server.js like http.createServer(app).listen(8080)? If you do, and access the app through localhost:8080 it wouldn't live reload client files, right? But if you would access localhost:9000 it would, but then again the node.js application isn't answering from there.. or am I doing it wrong? :) – acoder Mar 27 '13 at 18:16
  • No I don't setup an http.createServer(app). I use module.exports = app and when I do a require('./server') it returns 'app', which is an express app (every express app is a connect middleware). I just access the entire app on http://localhost:9000. – Sheena Artrip Apr 04 '13 at 21:58
  • It's fairly hackish, But I was able to get nodejs + connect/livereload + grunt to play nicely. https://github.com/sheenobu/yo-nodejs-example/commit/663509d7d7e41004c402e322292a9a4b14122002 – Sheena Artrip Apr 04 '13 at 23:00
  • 1
    Ahh, you're correct! Though, I just have to create server in the "server.js" since I'm using also socket.io, happen to have any medicine for that? – acoder Apr 06 '13 at 14:52
  • hrm. One option might be to separate out your socket.io stuff and your express http server stuff. Then, you can write a grunt task which starts the your socket.io on a separate port. – Sheena Artrip Apr 08 '13 at 16:47
1

My answer is using Gulp that I am more familiar with, instead of Grunt, but I imagine the same approach would work with Grunt as well.

See my repository (and an older one) and my other answer.

Neither any browser extension nor adding any script to your files is needed.

The solution is based on the gulp-livereload and connect-livereload packages working together. First, you start your live reload listener, and pipe into it any file changes (change * to any more specific node-glob to listen to only specific files):


var gulpLivereload = require('gulp-livereload');

gulpLivereload.listen();

gulp.watch('*', function(file) {
  gulp.src(file.path)
    .pipe(gulpLivereload());
});

Second, you configure your server to use the listener as middleware via connect-livereload:


var connect = require('connect');
var connectLivereload = require('connect-livereload');

connect()
  .use(connectLivereload())
  .use(connect.static(__dirname))
  .listen(8080);

See the packages for more information on how they work internally.

Community
  • 1
  • 1
Dmitri Zaitsev
  • 13,548
  • 11
  • 76
  • 110
0

In the Gruntfile, remove connect:livereload and open from server task.

Add following script in the HTML file

<!-- livereload script -->
<script type="text/javascript">
    document.write('<script src="http://'
        + (location.host || 'localhost').split(':')[0]
        + ':35729/livereload.js?snipver=1" type="text/javascript"><\/script>')
</script>
Fizer Khan
  • 88,237
  • 28
  • 143
  • 153