Start a server

Last updated on Oct 13rd, 2014

Using: grunt-contrib-connect

When working on a project on your machine you need a web server installed locally to test AJAX features or web fonts from services such as Typekit.

You might be tempted to use an AMP stack — a fancy way of calling a bundle of Apache, MySQL and PHP — but it's a hassle to link your projects to its www folder (I'm lazy) and most of the time you'll use 1% of its features anyway. Plus, let's be honest, it feels a little retro.

If you have Python installed, you can simply run this in your project folder instead:

python -m SimpleHTTPServer // for Python 2.x
python -m http.server // for Python 3.x

It will start a web server through which you can access your project at http://localhost:8000.

In this chapter, we'll learn how to configure the connect task to obtain a similar result, plus a few other perks.

Install the connect task

npm install grunt-contrib-connect --save-dev

and then load it into your Gruntfile:

grunt.loadNpmTasks('grunt-contrib-connect');

Configure a persistent server

To create a persistent server (one which does not stop after Grunt tasks have completed), we will use keepalive: true:

connect: {
    server: {
        options: {
            keepalive: true
        }
    }
}

We've created a single target called server for our connect task.

Run your server

grunt connect:server

Now go to http://localhost:8000 and you should be able to browse your app, and see your index.html if you have one.

More server configuration

You can customize the host name, port and protocol for your server:

connect: {
    server: {
        options: {
            keepalive: true,
            protocol: 'https',
            hostname: 'myapp',
            port: '8080'
        }
    }
}

The code above makes the server available at https://myapp:8080. This is useful in the case you want to start several servers at once, with different base directories, as in the example below:

connect: {
    first: {
        options: {
            keepalive: true,
            hostname: 'firstsite',
            base: 'first-site'
        }
    },
    second: {
        options: {
            keepalive: true,
            hostname: 'secondsite',
            base: 'second-site'
        }
    }
}

This makes the directories first-site and second-site from your project available at http://firstite:8000 and http://secondsite:8000, respectively.

Routing everything back to index.html

If you're writing a Single-Page Web Application that uses the HTML5 History API, you'll be disappointed to find that your skillfully crafted URLs don't withstand a page refresh. The web server assumes a path like http://localhost:8000/posts/100 points to a physical file and, failing to find it in your project, throws a 404 Not Found error.

Let's fix this by writing a custom middleware for the connect task to redirect paths that don't correspond to physical files back to index.html.

For this we will be using the connect-modrewrite plugin. It's not specifically written for Grunt, but we use it in the same way. Let's install it:

npm install connect-modrewrite --save-dev

And then use it in our Gruntfile:

var rewrite = require('connect-modrewrite');

Let's see how we can use it in our connect task:

var rewrite = require('connect-modrewrite');

grunt.initConfig({
    connect: {
        server: {
            keepalive: true,
            hostname: 'localhost',
            middleware: function(connect, options, middlewares) {

                // the rules that shape our mod-rewrite behavior
                var rules = [
                    '!\\.html|\\.js|\\.css|\\.svg|\\.jp(e?)g|\\.png|\\.gif$ /index.html'
                ];

                // add rewrite as first item in the chain of middlewares
                middlewares.unshift(rewrite(rules));

                return middlewares;
            }
        }
    }
});

We've written a custom middleware function which returns an array of chained middleware. We're inserting our rewrite middleware at the beginning of an existing chain which includes by default a static file server and which is sent to our function as the third argument. Our rewrite middleware contains a single rule which states that all files except HTML, stylesheets, scripts and images should be redirected to index.html.

Testing on other devices

To make our app available to other devices — like a phone or tablet connected to the same network as our development machine — we need to make one small adjustment:

hostname: '*'

Now you can test your app on any device by going to http://ip-address:8000.

Note: To find out your machine's IP, run ifconfig in the command line and look for the IP next to inet addr. On Windows, you run ipconfig and look for IPv4 Address.

Take five

In this recipe, we've done quite a few things: