Skip to content

Live reloading using Grunt.JS task runner

Every so often I come across a tool that is so impressive that it changes the way I do things forever. Grunt.JS is one of those tools. It uses Node.JS to run tasks such as compiling SASS into CSS or compiling CoffeeScript into JavaScript. One of the main features is it can watch you filesystem for changes and perform tasks based on these changes. We are going to use this to watch changes in our files and reload the page to the browser when it finds them.

Creating the project and installing the dependencies

Grunt.JS depends on Node.js versions >= 0.8.0 and the Node Package Manager (NPM). Make sure these are installed on your system before proceeding.

http://nodejs.org/download/

Once Node.js and NPM are installed, let’s create a folder for our project and install some dependencies we’ll be using.

mkdir ./project
cd project
npm install grunt

This will install Grunt.js to the project directory.

Grunt.js has load of modules that can be installed via NPM. We need a couple of these in order to complete our live reloading task. The first one is called grunt-contrib-watch which is the module that will be watching our files.

npm install grunt-contrib-watch

Another dependency that we will be using is matchdep which will help our app match the dependencies that we will be defining in our projects package.json file.

npm install matchdep

Package.json

The package.json file usually resides in the root of your project and contains any meta information about your project, including it’s dependencies. More information here.

We need to create this file and add some information. Make sure you are in project directory.

nano package.json

Then add the following

{
    "name": "test-project",
    "version": "1.0.0",
    "devDependencies": {
        "grunt": "~0.4.1",
        "grunt-contrib-watch": "~0.4.3"
    }
}

So we have defined a name for our project and defined some dependencies. The matchdep package we installed earlier will be reading the dependencies list from here.

Gruntfile.js

The Gruntfile.js file is at the heart of the operation. You will define all of your tasks here. We want to create a task that watches a folder and reloads the page when it detects changes have been made to the filesystem. We have already installed the grunt-contrib-watch module to handle this, so let’s create a Gruntfile.js and add this here. Make sure you are in project directory.

nano Gruntfile.js

Then add the following

module.exports = function(grunt) {
 
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
 
    grunt.initConfig({
 
        watch: {
            all: {
                options: {
                    livereload: true
                },
                files: ['app/*']
            }
        }
 
    });
 
    grunt.registerTask('watch-this', 'watch');
}

Note the matchdep being loaded before Grunt is initiated. It looks for all Node modules prefixed with grunt-.

Also, let’s have a look at the watch config. The livereload option is bundled by default in Grunt, so all we need to do is enable this. We will create a directory called app and watch all files inside it. Obviously in most cases you won’t want to watch for all file changes inside a directory so you would configure this to only watch certain directories/files.

The grunt.registerTask method will create a task called watch-this which will run watch when a server has been created.

The app

Let’s create a new directory for our app files. Make sure you are in your project directory.

mkdir ./app
touch app/index.html

This will have created a new directory inside your project directory named app and would have created a file called index.html

Running the task

Make sure you are in your project directory and in the terminal type grunt watch-this. This will create a Node.js server running on port 35729. So, if you navigate to http://localhost:35729/ you should see the following if all is well.

{"tinylr":"Welcome","version":"0.0.4"}

This confirms that our task is being run in the background. So now we need to create a link in our index.html file so that it knows it’s being watched.

nano app/index.html
<script src="http://localhost:35729/livereload.js"></script>

Save and open index.html in your web browser. You’ll get a blank page. Try to get your terminal window and browser window side by side.

Make some changes and marvel at the magic!

nano app/index.html
<script src="http://localhost:35729/livereload.js"></script>

Hello World!

Save index.html and watch the browser update. Magic.

If you get an issue starting the watch task

I did run into an issue when starting the watch task. An error like the following would occur.

Running "watch" task
Waiting...Fatal error: watch ENOSPC
Fatal error: Maximum call stack size exceeded

I was able to find a solution for this on Stack Overflow.

Before running the task, type this into the console.

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf &amp;&amp; sudo sysctl -p

Turns out there is a cap on the number of watches per user. If you have other tasks running, like me, it would just fail to spawn new tasks such as our one here.

About 

I run a small web development agency in Salisbury, UK. We provide both front-end/back end solutions and infrastructure management. My specific role is to identify the needs of our clients and providing an online solution that is easy to administer, secure, scalable and maintainable.

 

My agency website is white-fire.co.uk. Contact us if you need a consultant.

Published inJavaScript

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *