You’ve learned a lot.
You should earn a lot.

Find a Job

A Fast and Convenient Development Server with lite-server

Workflow automation is such an essential aspect of modern web development that's it hard to imagine building anything without a build step.

Gulp, Browserify, and Webpack have scratched the itch, each in different way. All three can be a bit of a hassle to set up from scratch, however, and even solid workflows provided by tools like Yeoman generally require a bit of tweaking if they're to suit your needs.

That's fine for large projects with a complicated build pipeline, but if all you need is a development server and live-reload functionality to begin exploring a new project domain, however, setting up a full-scale build tool just to get started is probably time wasted.

That's where lite-server (created by John Papa and Christopher Martin) comes in.

A Server's All You Need

Firing up a server with Node.js is pretty darn close to the easiest thing you can do with it. All things considered, it's not hard to start setting up a development server on your own:

"use strict";
const  fs    = require('fs'),
        http = require("http");

http.createServer(function (request, response) {

console.log('Listening on port 8000.');

Setting up all the boilerplate to handle your routes is obviously no better than spending the time to spin up a build tool, though.

Browsersync is a lightweight, highly configurable development server designed to automate cross-browser and multi-device testing as much as possible. lite-server takes things a step further by offering a thin, preconfigured wrapper around BrowserSync.

If Browsersync lets you get started quickly, lite-server lets you get started immediately. Simple as that.

But don't take it from me. Take it from the Angular team. They've embraced it as the official dev server for the Angular 2: Tour of Heroes tutorial.

I don't know about you, but I'm not one to argue with them.

Let's get started.


There are two ways to instal lite-server:

  1. System-wide, using: npm install --global lite-server
  2. Locally to n NPM project, using npm install lite-server --save-dev

We'll go the second route, as that's what John Papa and Christopher Martin (lite-server's creators) recommends.

First, create a directory somewhere, initialize it as an NPM project:

mkdir lite-server-example && cd $_
npm init

And in index.html:

<!doctype html>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
        .jumbotron { font-size: 4rem; text-align: center; }


    <div class="jumbotron">
        Hello, world! This is HTML5 Boilerplate.


Next, install lite-server:

npm install lite-server --save-dev

Finally, add the following to the scripts object in your package.json:

"dev" : "lite-server"

We have to do this because running lite-server from the command line will search for a global installation instead of searching your local node_modules directory. If you installed lite-server globally, that's fine: You won't need to add that line to your package.json, and you can simply run:


Otherwise, run:

npm run dev

Either way, you'll notice lite-server spin up a server and open your index.html in a web-browser.

lite-server serving index.html

Under the hood, it's also watching for changes to any HTML, CSS, or JavaScript files in your project's root folder or lower.

lite-server in action


Browsersync Configuration Options

Here's a secret about lite-server: It's just Browsersync. If you're going to be using lite-server, it pays to get up to speed on it.

All you need to do to take advantage of Browsersync's underlying power is write a bs-config.json that sets any of Browsersync's configuration options.

This config sets a custom base directory; set a custom watchpath; enable (local) HTTPS; and launch our app in both Google Chrome and Firefox.

    "files" : "./src/**/*.{js, html, css}",
    "server" : { "baseDir" : "./src" },
    "https" : true,
    "browser" : ["google-chrome", "firefox"]

For general-purpose web-development, this is probably as far as you'll need to go. There's a sea of options for your specific use cases, though; don't be shy about tinkering if you need to.

By default, lite-server disables injectChanges and excludes your local node_modules directory from its file watch, so you don't need to set these options yourself. It also enables some lightweight middleware, which we'll talk about shortly.

Custom Middleware

Middleware refers to any processing the server performs between receiving a request and responding to it, such as setting headers on outgoing requests or authenticating users before sending sensitive information.

lite-server provides two middlewares by default:

  1. connect-logger, which prints a timestamp, request type, and HTTP status code to the console on each request; and
  2. connect-history-api-fallback, which redirects to the index.html in your base directory if the client requests a non-existent route.

If you need more, you need to replae your bs-config.json with a bs-config.js. This is because using middleware requires you to either define your own functions, or require someone else's. Either way, JSON won't do the job; you'll need raw JavaScript.

You'll still end up setting your configuration in JSON, but you'll use module.exports instead of writing JSON file. Converting the conig we have above looks like this:

// bs-config.js
"use strict";

/// Export configuration options
module.exports = {
    "files" : "./src/**/*.{js, html, css}",
    "server" : { "baseDir" : "./src" },
    "https" : true,
    "browser" : ["google-chrome", "firefox"]

From here, adding middleware is straightforward. The Browsersync Recipes repository has a LESS middleware example, which compiles LESS and injects the resulting CSS whenever the clien requests a file with the .less extension. Let's see how we'd add it to our configuration.

"use strict";
var browserSync = require('browser-sync');

function lessMiddleware (req, res, next) {
    // Adapted directly from Browsersync exampes:
    //   https://github.com/Browsersync/recipes/tree/master/recipes/middleware.css.injection

    var parsed = require("url").parse(req.url);
    if (parsed.pathname.match(/\.less$/)) {
        return less(parsed.pathname).then(function (o) {
            res.setHeader('Content-Type', 'text/css');

    function less(src) {
        var f = require('fs').readFileSync('app' + src).toString();
        return require('less').render(f); 

/// Export configuration options
module.exports = {
    "files" : "./src/**/*.{js, html, css}",
    "server" : {
        "baseDir" : "./src" ,
        "middleware" : {
            2 : lessMiddleware
    "https" : true,
    "browser" : ["google-chrome", "firefox"]

Two things to take note of here.

First, since we're require-ing the browser-sync and less modules, you'll need to install them for this to work:

npm install --save-dev less browser-sync

This is true of any module you require middleware you write. This is basic Node.

Second, note that we've added a middleware key under the server object of our module.exports, and that we've set our custom lessMiddleware as the value for the key 2. This is because lite-server already provides two middlewares by default. These are represented internally as middleware.0 and middeware.1. If we want to add to that list rather than replace it, we have to set our middleware equal to numerica keys, starting at 2 and moving up.

If were to set it this way instead:

middleware = lessMiddleware

. . . We'd end up throwing out the defaults, because lite-server would treat lessMiddleware as the new, andonly middleware.

On that note, if you want to disable one of the two defaults, you can set its value to null; and if you want to completely override them with your own set of middleware, you can set the middleware key's vaue to an array containing your selections:

/* Disabling connect-logger */
"middleware" : {
    0 : null

/* . . . Or, replacing defaults with a custom set of middleware */
"middleware" : [lessMiddleware, coffeeMiddleware, myOtherAwesomeMiddleware]

/* . . . Or, replacing defaults with a single middleware */
"middleware" : lessMiddleware

The details of writing middleware are beyond the scope of this article. But, as both default middlewares are built atop the Connect framework, you can expect most modules endorsed by that project to work with a minimum of fuss.


By now, you should be comfortable enough with lite-server to:

  • Install and run lite-server;
  • Use Browsersync options to customize lite-server's behavior; and
  • Configure custom and third-party middleware.

For a more thorough introduction to Browsersync, check out How to Use BrowserSync for Faster Development, as well as the official documentation on config options.

Feel free to leave questions or confusions in the comments -- I'll get back to you. And, if you just can't wait for an answer, hit me on Twitter (@PelekeS).

Peleke Sengstacke

Peleke Sengstacke is a web and Android developer with a soft spot for functional programming.

He likes linguistics, Haskell, and powerlifting. He dislikes mosquitoes, cramped bus rides , and merge conflicts.

Catch him on Twitter (@PelekeS), or sign up for his email list on what to learn and where to learn it (http://www.tinyletter.com/PelekeS). It's wicked educational.