Monday, 7 May 2012

node.js boilerplate - client side templating; express 3.0

Introduction
The race by browser developers to develop even faster JavaScript engines has made client side templating a realistic alternative to server side templating. Any decision to use client side templating is very much a tradeoff; the following should be considered:

Client side templatingServer side templating
Server/client performanceFaster server response; slower on clientSlower server response; faster on client
BandwidthServes a smaller JSON response; but will also need to request the javascript template engineServes larger HTML response; no extra javascript libraries
Javascript ClientsMust have javascript enabledJavascript not required
Search Engine friendlyNo; will need to sniff out search engine bots and serve them HTML Yes
CachingCache templates & JSONCache entire response of some pages
Seperation of ConcernsCleaner split; enabling HATEOS allowing client and server to evolve independentlyServer returns entire HTML response; client and server coupling
Multiple DevicesServe JSON to alternative devicesRequires client sniffing in order to serve appropriate response

Our boilerplate will support both client and server side templating; it will also support template pre-compilation.

Content Negotiation
In order to support both client and server side templating from within the same application we need to be able to serve JSON and HTML. express supports content negotiation; see below example; which is an HTTP concept whereby a resource can be represented in multiple formats; a HTTP requests accept header will determine which representation is returned.

The below route for our homepage demonstrates how content negotiation works in express; we will serve JSON for our client side templating and HTML for server side templating.


API
Below is the api for our home page referred to in the above snippet; its loosely based on a REST architecture constraint known as HATEOS - Hypermedia as the Engine of Application State; which is effectively a decoupling of client/server allowing both to evolve independently. The concept is actually very simple when a client requests a resource the server will return a response which contains a series of hypermedia based interactions; links essentially to the various actions the user can now perform based on the current state; but I degress.


Server Side Templating
Consolidate.js allows us to abstract away any server side templating engine we decide to use with express providing us with a consistent api when rendering views; configuring consolidate.js is very simple; simply add the following piece of configuration to your main node/express application; our app will now support dust.js:


Client Side Templating
Templating on the client side works by configuring express to serve a JSON response. Ideally a CDN/cache server will serve the HTML templates; our boilerplate application is configured to allow express to serve these; but this is really just to demonstrate the concept. The HTML template will make an AJAX call to get any data the page requires; the template engine will then load the data into the view.

Further performance gains can be accomplished by pre compiling the template and saving it to a JavaScript file, thus avoiding compilation on the client. You can also then request the runtime version of dust.js which is considerably smaller than the full version required when compiling on the client.

Client side templating with pre compiled templates
In order to pre-compile dust.js templates I have put together a simple node.js console application dust-down which will compile all dust.js templates in a given folder. The snippet below also includes in a script tag the pre-compiled templates.


Client side templating with client side template compilation
This is basically the same as the snippet above but does not include any pre-compiled templates; these are compiled on the client. This also requires the full version of dust.js.



Test drive
In order to test drive the various templating options, edit the views located here:
node-plates\node.jquery.mobile\public\views
You will see below three templating options; comment in/out the templating option you are testing


Now start the node-plates application:
node server.js

Make sure you comment in/out the correct scripts in each view:

To see server side templating open a browser and visit the below; express is serving this via the routing for HTML we have setup :
http://127.0.0.1:3000/about

To see client side templating open a browser and visit the below; express is serving this via the built in static file server; i.e. any files in the public folder are served this way. The HTML template will make a AJAX/JSON call to get the data for this page:
http://127.0.0.1:3000/views/about.html

About
This post is part of a series of posts tagged under node-plates a boilerplate mobile/web application written in node.js, express, socket.io, mongooose, jquery.mobile & html 5.

Github
You can grab this from github ->
https://github.com/AndrewKeig/node-plates

References
akdubya.github.com/dustjs/
github.com/visionmedia/consolidate.js
github.com/AndrewKeig/dust-down

3 comments:

  1. A really interesting read.

    However, I fail to understand how you can compile the template based on the page HTML?

    var compiled = dust.compile($('#index').html(), 'index');

    It will returns you pure HTML, with no dust.js tags, and thus, when you render it with the client-side, it will keep render the same HTML regardless of whatever context you pass in.

    ReplyDelete
  2. hey thanks;

    var compiled = dust.compile($('#index').html(), 'index');

    The above line will perform a client side compilation on each request of the page; the option you are referring to is not the pre-compiled option; so yes; it will render the same html.

    The pre-compiled option actually compiles these html pages down to a javascript function; you simply include it on the page as a normal javascript include and load it.

    Cheers

    ReplyDelete
  3. Hi fellas!

    Everything is clear except when , where and how is the dust.js file is invoked?
    In your code ex: node-plates.js

    Also in a normal scenario, where will this js(node-plates.js) file be??
    in the CDN or in the server side ??

    ReplyDelete