Making Browser Refresh in Response to Our Sources Modification

We all are taught not to repeat ourselves while coding. Nonetheless we keep repeating the same operation over and over – pressing F5/Ctrl-R for browser reload every time we have to examine the results of our last changes. After watching some of Paul Irish screencasts where he was showing the magic of live reload under Sublime Text 2 I wondered if I could employ something alike while keeping working with my beloved NetBeans IDE. However in my case it wouldn’t be enough just to reload the page when any of watched files change. I need to compile SASS sources, combine atomic JavaScript chunks into a single module and sometimes flush the application cache.

Eventually I found a tool meeting all requirements I have. It turned out that Grunt task runner has a plugin grunt-contrib-watch , which keeps track of files modification events and fires up all the assigned tasks when a modification detected. Right after that the plugin triggers event by which the live reload script

updates the subscribed pages. As far as Grunt runs the ‘watch’ task provided by the plugin the live reload script is available on the configured port (35729 by default)

Configuring Grunt

As you see this approach requires Grunt. If don’t have that tool, it’s not a big deal. Grunt is available as a [nodejs|nodejs.com] package. So you can install Grunt globally using following command:

npm install -g grunt

To let Grunt know about your project you have to place package.json in the root of your project directory. It may look like that:

package.json

{
  "name": "project-name",
  "title": "Project title",
  "version": "0.1.0",
  "homepage": "http://site.com"
}

Grunt configuration is expected in the file Gruntfile.js. Let’s start with a simple job – refreshing browser window when any of the watched files modified:

Grunfile.js

module.exports = function( grunt ) {

  grunt.loadNpmTasks('grunt-contrib-watch');
  
  grunt.initConfig({
     watch: {
        options: {
          livereload: true
        },
        css: {
            files: [ 'css/**/*.css' ],
            tasks: [ 'default' ]
        },
        js: {
            files: [ 'js/**/*.js' ],
            tasks: [ 'default' ]
        }
      }
  });
  grunt.registerTask( "default", [ "watch" ] );
};

What is going on in here? We inform Grunt that we want to live reload for any files in css and js directories. This task obviously requires grunt-contrib-watch plugin. So we extend our package.json with the required dependencies list:

package.json

{
  "name": "project-name",
  "title": "Project title",
  "version": "0.1.0",
  "homepage": "http://site.com",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "~0.4.4"
  }
}

Now we can get these dependencies resolved by nodejs package manager:

npm i

On all the project pages where you want live reload you add live reload script:

<script src="http://localhost:35729/livereload.js"></script>

Just make sure it doesn’t show up anywhere out of development environment.


Starting live reload server

As we have everything ready we can launch the server by running Grunt for the default job (as we have configured):

grunt

Try now changing CSS and JavaScript files and examine as browser refresh window in the response.

So what about extra tasks I was telling about in the very beginning? We plainly extend our Gruntfile.js with new jobs configuration:

Gruntfile.js

module.exports = function( grunt ) {

  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-compass');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks("grunt-jsic");

  grunt.initConfig({
     compass: {
        dist: {
          options: {
            sassDir: 'sass',
            cssDir: 'wwwroot/build/'
          }
        }
     },
     jsic: {
        files: [ "js/index.js", "./wwwroot/build/script.js" ]
     },
     clean: [ "cache/*.*" ],
     watch: {
        options: {
          livereload: true
        },
        css: {
            files: [ 'sass/**/*.sass' ],
            tasks: [ 'compass', 'clean' ]
        },
        js: {
            files: [ 'js/**/*.js' ],
            tasks: [ 'jsic', 'clean' ]
        }
      }
  });

  grunt.registerTask( "cleanup", [ "clean" ] );
  grunt.registerTask( "build", [ "compass", "jsic" ] );
  grunt.registerTask( "default", [ "watch" ] );

};

Now when any of SASS files modified Grunt re-compiles the CSS and flushes the cache afterwards. If any of JavaScript sources changed it compiles the module and again cleans up the cache.

As you see here we use some additional Grunt plugins. So we have to add the new dependencies into package.json:

package.json

{
  "name": "project-name",
  "title": "Project title",
  "version": "0.1.0",
  "homepage": "http://site.com",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-watch": "~0.4.4",
    "grunt-contrib-jshint": "~0.4.3",
    "grunt-contrib-compass": ">=0.3",
    "grunt-contrib-clean": ">0.0.1",
    "grunt-jsic": ">= 0.0.1",
    "jsic": ">= 0.1.2"
  }
}

Now when we start the server and make any changes of the watched files the Grunt output will be like that:



Caveats

By and large grunt-contrib-watch serves me well. However if I happen to save a SASS file with an invalid syntax, something goes really wrong. One has to save the fixed files many times until the restored CSS gets available on the refreshing page.