Check out "Do you speak JavaScript?" - my latest video course on advanced JavaScript.
Language APIs, Popular Concepts, Design Patterns, Advanced Techniques In the Browser

Node.js application made with Express and AbsurdJS

Node.js is one of those new technologies, which are attracting more and more developers every day. Mainly, because it's JavaScript driven, a lot of people are interested working with it. In this tutorial, I'll show you how to use AbsurdJS together with Express. Express is one of the popular Node.js frameworks. However, the other instrument is really fresh one and I hope that you will find it useful.

Introduction

As I said, Express is really popular. That's because it was one of the first frameworks for Node.js. It does all these trivial tasks, like routing, parameters parsing, templating, sending response to the browser. The library is a nice wrapper around the Node.js native stuff. It's based on the middleware architecture provided by Connect.

AbsurdJS started as a CSS preprocessor. The main purpose of the module was to give more flexibility to the CSS developers. AbsurdJS accepts plain JavaScript and converts it to CSS. The feedback about it was positive, and I continued working on it. Today it's not only preprocessing CSS, but also HTML. It accepts JSON and YAML and it is successfully ported for client-side usage.

Setup

To get a working application in the end, we need Node.js installed. So, just go to nodejs.org and click the big green button INSTALL. Once everything is downloaded and installed on your system you will be able to call Node.js scripts and install dependencies with npm (the Node's package manager).

Create a new folder for our project and put an empty package.json file. The package manager uses this file as a starting point and installs what we need. We need only two things, so the json should look like that:

{
    "name": "AbsurdJSAndExpress",
    "description": "AbsurdJS + Express app",
    "version": "0.0.1",
    "dependencies": {
        "express": "3.4.4",
        "absurd": "*"
    }
}

Of course, there are tons of other stuff, which we can add. But because that's just an example we will stick with only these options.

Open your console, navigate to the directory which contains the package.json file and execute:

npm install

This will create a folder called node_modules and will place Express and AbsurdJS there.

Running the server

Thankfully to Express you need just few lines to run a http server.

var express = require('express'),
    app = express();

app.listen(3303);
console.log('Listening on port 3303');

Save the above code as app.js and run:

node app.js

You should see Listening on port 3303 in your console. And our server is now listening on port 3303. If we open http://localhost:3303/ we should see that it is responding with:

Cannot GET /

This may look bad, but it is normal, because we didn't add any routes.

Adding routes

Express has a nice API for defining URL routes. Let's add a very simply one. Put the following code in app.js:

app.get('/', function(req, res, next) {
    res.setHeader('Content-Type', 'text/html');
    res.send("application");
});

Few things are happening here. The first argument of .get method defines the path and the second one is a function which will handle the request. It accepts three parameters - request, response and next. The good thing is that we can pass not only one, but as many functions we want. They will be called one after each other. The only one thing that we should care about is to execute next(). Otherwise the next method will not be reached. For example:

app.get(
    '/', 
    function(req, res, next) {
        console.log("do some other stuff here");
        next();
    },
    function(req, res, next) {
        res.send("application");
    }
);

It's a common practice to add repeatable tasks as middlewares during the route definition. For example, in our case, we will have two different content types - HTML and CSS. We could make the things a little bit more flexible by adding function for that.

var setContentType = function(type) {
    return function(req, res, next) {
        res.setHeader('Content-Type', 'text/' + type);
        next();
    }
}
app.get('/', setContentType("html"), function(req, res, next) {
    res.send("application");
});

If we need to serve CSS we just have to call setContentType with another parameter.

Serving the HTML

Most of the tutorials and articles about Express introduces some template engine. Pretty often that's Jade, Hogan or Mustache. However, if we use AbsurdJS we don't need a template engine. We could write our HTML with pure JavaScript. To be more specific - JavaScript objects. Let's start by writing our landing page. Create a new folder called pages and put landing.js there. We are in the world of Node.js so the file should contain:

module.exports = function(api) {
    // ...
}

Notice that the returned function accepts a reference to AbsurdJS's API. That's all we need. Now, let's add some HTML:

module.exports = function(api) {
    api.add({
        _:"<!DOCTYPE html>",
        html: {
            head: {
                'meta[http-equiv="Content-Type" content="text/html; charset=utf-8"]': {},
                'link[rel="stylesheet" type="text/css" href="styles.css"]': {}
            },
            body: {}
        }
    });
}

The _ property adds raw string to the compiled HTML. Every other property defines a tag. There is an alternative syntax for defining tag attributes, but I think that the one used above is much better. I got this idea from the Emmet plugin for Sublime. After the compilation you will get:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <link rel="stylesheet" type="text/css" href="styles.css"/>
    </head>
    <body/>
</html>

This tutorial has only one page, but in real life you may have the same HTML used in a lot of pages. It makes sense to move this piece of code in an external file and reference it when needed. Of course, there will be some other things which you will recognize as repeatable templates. Let's create a directory /pages/partials and put them there. The first /pages/partials/layout.js looks like that:

module.exports = function(title) {
    return {
        _:"<!DOCTYPE html>",
        html: {
            head: {
                'meta[http-equiv="Content-Type" content="text/html; charset=utf-8"]': {},
                'link[rel="stylesheet" type="text/css" href="styles.css"]': {},
                title: title
            },
            body: {}
        }
    };
};

It's just a function which returns an object. So, the code of our landing.js could be changed to this:

module.exports = function(api) {
    var layout = require("./partials/layout.js")("Home page");
    api.add(layout);
}

Notice that the layout template accepts title variable. That's how you make the partials' content dynamic.

The next logical step is to add content to the body tag. And because everything is just plain JavaScript objects it's really easy.

module.exports = function(api) {
    var layout = require("./partials/layout.js")("Home page");
    layout.html.body = {
        h1: "Page content"
    }
    api.add(layout);
}

The result is:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <link rel="stylesheet" type="text/css" href="styles.css"/>
        <title>Home page</title>
    </head>
    <body>
        <h1>Page content</h1>
    </body>
</html>

The code which comes with the article contains a lot more partials, but if I have to write them all here, the post will be too long. I'll present only the idea of building unordered lists, because it's a little bit more interesting. The rest of the things are written the same way as the layout it is.

Here is the partial which is generating unordered list, i.e.

    tag.

    module.exports = function(data) {
        var html = { ul: [] };
        for(var i=0; item=data[i]; i++) {
            html.ul.push({ li: item });
        }
        return html;
    }
    

    It defines an object with only one property ul. The value of the property is actually an array (not an object) and later that array is filled with the items of the list. For example:

    var list = require("./partials/list.js");
    var link = require("./partials/link.js");
    list([
        link("http://krasimir.github.io/absurd", "Official library site"),
        link("https://github.com/krasimir/absurd", "Official repository")
    ]);
    

    link is also partial, which looks like that

    module.exports = function(href, label) {
        return { 
            a: { _attrs: { href: href }, _: label }
        }
    }
    

    When everything is combined the result is:

    <ul>
        <li>
            <a href="http://krasimir.github.io/absurd">
                Official library site
            </a>
        </li>
        <li>
            <a href="https://github.com/krasimir/absurd">
                Official repository
            </a>
        </li>
    </ul>
    

    Now, imagine that we have a bunch of ready to use partials. We could create them once and if they are flexible enough, to transfer them from a project to project. AbsurdJS is powerful, because if we have a proper collection of the predefined stuff, we are able to work fast and be more descriptive while writing HTML markup.

    At the end, when the HTML is done, we just have to compile it and send it to the users. So, a little change in app.js makes our application responding with proper markup.

    var absurd = require("absurd");
    var homePage = function(req, res, next) {
        absurd().morph("html").import(__dirname + "/pages/landing.js").compile(function(err, html) {
            res.send(html);
        });
    }
    app.get('/', setContentType("html"), homePage);
    

    Serving CSS

    Similar like with the HTML, we should add a route to styles.css. In our app.js:

    var styles = function(req, res, next) {
        absurd().import(__dirname + "/styles/styles.js").compile(function(err, css) {
            res.send(css);
        });
    }
    app.get('/styles.css', setContentType("css"), styles);
    

    Again, the definition of the CSS is made with JavaScript. Everything could be placed in nicely separated Node.js modules. Let's create /styles/styles.js and put some code inside:

    module.exports = function(api) {
        api.add({
            body: {
                width: "100%",
                height: "100%",
                margin: 0,
                padding: 0,
                fontSize: "16px",
                fontFamily: "Arial",
                lineHeight: "30px"
            }
        })
    }
    

    A basic styling. Notice, that the properties which contain a dash are written in camel case style. Otherwise, the object will not be valid and you will get an error.

    Let's say that we need to style

    and

    tags. They are both titles and we will have same color and font, but the size will be different. Thankfully AbsurdJS is smart enough to apply the correct styles if we pass the correct objects.

    var title = function() {
        return {
            color: "#2C6125",
            fontWeight: "normal",
            fontSize: "40px",
            fontFamily: "Georgia",
            padding: "20px 10px"
        }
    } 
    api.add({
        h1: title(),
        h2: [
            title(), 
            { fontSize: "30px" }
        ]
    });
    

    The result of the code is

    h1, h2 {
        color: #2C6125;
        font-weight: normal;
        font-family: Georgia;
        padding: 20px 10px;
    }
    h1 {
        font-size: 40px;
    }
    h2 {
        font-size: 30px;
    }
    

    Notice, that the preprocessor collects same styles in only one definition and creates a new one only for the differences.

    Conclusion

    If we plan to work with Node.js, Express, is one of the best starting points. It's not that big, but it is still helpful. It has everything we need to start developing our web application. Extending it, by adding AbsurdJS makes the things really interesting. Mainly because the whole application is written with pure JavaScript.

    Resources

    If you enjoy this post, share it on Twitter, Facebook or LinkedIn.