Serving Single Page Apps with Live-server

This will be a quick one ... I'll be using a global installation of live-server, a node package to serve a single page app having custom routes built with AngularJS.

To install live-server globally, run the following command in your terminal:

npm install -g live-server  

The angular app uses the angular ui-routing library, so I have the following routes:

  • /
  • /users
  • /users/:userId
  • /users/:userId/edit
  • /about
  • Also, this => /index.html (static file to be served by default)

I won't go into how to use the angular-ui-router library ... A really good beginner tutorial I use everytime can be found here.

It's expected that the root/base html file (in this case, index.html) should be served by the server when the inner routes are requested.

E.g.:

When the /users or /about routes are requested, we want the server to render the index.html file in the response.

Brief Intro to Middlewares

Luckily, live-server comes with a --middleware={middleware-file.js} flag so we can specify a JavaScript file that exports a middleware function.

This function will check whether the url matches any of an array of regular expressions.

  • If it does, it will serve the index.html file.
  • Else, it'll hand over the request to live-server to do with as live-server pleases.

A very simple middleware function is:

module.exports = function (req, res, next) {  
    next();
})

The function above doesn't really do anything. It just hands over to the next item in the NodeJS control flow. In this case, live-server.

So let's write our array of regular expressions, yea?

var indexRoutes = [  
    "^\/users",
    "^\/about$"
];

The first regex string targets all /users/** routes, so it will match /users, /users/:userId and /users/:userId/edit.

The second regex string targets the /about route.

Now, let's serve the index.html file when the request matches these regex strings.

We'll need to be able to access the file-system, and we'll make use of the fs module for this, so:

const fs = require("fs")  

Let's have the full code now:

const fs = require("fs")

module.exports = function (req, res, next) {  
    var indexRoutes = [
        "^\/users",
        "^\/about$"
    ];
    if (indexRoutes.find(function (route) {
        return req.url.search((new RegExp(route))) == 0;
    })) {
        fs.readFile("./index.html", "binary", function (err, file) {
            if (err) {
                res.writeHead(500, { "Content-Type": "text/plain" });
                res.write(err + "\n");
                res.end();
                return;
            }

            res.writeHead(200);
            res.write(file, "binary");
            res.end();
        });
    }
    else next();
}

And there we have it. You can go on to save the file as middleware.js anywhere in your rootfolder.

Now run live-server in your console with the following command:

live-server --middleware="{root-path}\server.js"  

Be sure to replace {root-path} with the actual path to your root folder like C:\Users\MyPC\Documents\Websites\test-app

What we accomplished

  • We didn't have to setup express for this
  • Perhaps, we learned to use the fs module to serve static files
  • We learned to use live-server's middleware functionality to customize the way it works.
Show Comments