Nodejitsu

Save time managing and deploying your node.js app. Code faster with jitsu and npm

Micro Templates Are Dead... forget about it.

About the author

Name
Location
Worldwide
nodejitsu nodejitsu

Don't like that title? You probably disagree. That's because "micro templating" is a subject of contention. Everyone has their own idea of how it should work. People argue about which engine is N milliseconds faster than the next, or why one should use curly braces instead of angle brackets. A divided community rearranges the deck chairs on the titanic. In this article, we explore the ineptitudes of traditional micro templating. As well as demonstrate how Node.js can untangle the mess.


The problem

Today, most templating requires you to pepper your markup with 'stubs' or 'placeholders'. Like Java JSPs or Django Templates. It may remind you of the 90's...

<div id='<%=futureData%>'>foo</div>
<ul>{%for d.length}<li id='{%d.futureData}'></li>{%end for}</ul>

It's non-standard, and it's a hack. Blending decision making into your presentation layout will lead to maintenance problems as the complexity of your program grows. As well, it will become more challenging for designers to manipulate and understand the new aspects and rules of the front-end they are working with. Why did anyone ever do this? It's just the evolution of web frameworks. In the beginning, web server frameworks treated html files like raw strings because they didn't have a working DOM. Here's an example...

<div id='foo'><%=futureDataGoesHere%></div>

ends up getting parsed, evaluated, and regurgitated as...

<div id='foo'>some new value</div>

Even worse. lets say you are a front-end developer or maintainer. You're inspecting the DOM, trying to find out why a style is only sometimes wrong. You deduce there are conditions in the HTML! Now you need to look at the file on the server. Goodness! There's some cryptic syntax in that markup! You could trace hundreds of lines of Python or Java, but you're a front-end developer, so forget that. Consider it a wild goose chase and file a bug. OR you can go node.js FTW.

<%=if(userAge=='35'){>
  <div class='<%=whyIsTheCSSborked%>'></div>
<%=}>

The solution

If the web server had a working DOM, we could maintain the purity of the document and the node we want to manipulate would be accessible to our externalized decision-making code. We should have the same abilities on the server as on the client...

Markup...

<div id='myId'></div>

Code...

$("#myId").html("blam-o!!");

Why is that good? It's standards compliant. No workarounds like <%=foo%> or {$bla}. It promotes portable code by decoupling presentation from decision making. Can this be really done? Yes!

Node.js has a working DOM, its called JSDOM. This in concert with Weld, our data/DOM mapping tool, is all you need to build markup that is populated with data and ready to serve. Let's take a look at these tools in action. First we'll load jQuery, then get some data. It doesn't matter where the data comes from. For simplicity's sake let's just use an array of objects.


Welding data to the DOM.

var fs = require('fs'),  
    jsdom = require('jsdom'),

jsdom.env({  
  scripts: [
    '/../lib/jquery.js',
    'https://github.com/hij1nx/weld/raw/master/lib/weld.js'
  ],
  html: 'contacts.html'
},
function (errors, window) {

  var $ = window.jQuery;

  var data = [
    { 
      name: 'hij1nx',  
      title : 'code slayer' 
    },
    { 
      name: 'tmpvar', 
      title : 'code pimp'; 
    }
  ];

  $('.contact').weld(data);
});

Here is the corresponding markup that our script above will load...

<ul class="contacts">  
  <li class="contact">
    <span class="name">My Name</span>
    <p class="title">Leet Developer</p>
  </li>
</ul>  

And here's what it will produce...

<ul class="contacts">  
  <li class="contact">
    <span class="name">Paolo</span>
    <p class="title">Code Slayer</p>
  </li>
  <li class="contact">
    <span class="name">Elijah</span>
    <p class="title">Code Pimp</p>
  </li>  
</ul>  

I bet you're thinking "what just happened?" Exactly! By default, Weld uses a heuristic that assumes each of the keys in the data's key: value pairs is an '#id', a '.class' or 'name' in the template's HTML. This addresses the 80/20 of cases. If you want, you can supply more explicit instructions by providing a bind parameter which maps selectors to keys in your data.

To be more explicit during binding, let's say you have html where a span has the class 'name', but you don't want the data with the key 'name' to map to that, you want it to map to something else...

<ul class="contacts">  
  <li class="contact">
    <span class="name">Hello my name is <span class="firstAndLast">My Name</span></span>
    <p class="title">Leet Developer</p>
  </li>
</ul>  

Let's say this is the data to bind...

var data = [  
  { 
    name: 'Paulo',  
    title: 'code exploder' 
  },
  { 
    name: 'Elijah', 
    title: 'code pimp' 
  }
];

Just add explicit assignments with the bind parameter...

weld('.contact', data, {  
  bind: { 
    'name': '.firstAndLast', 
    'title': '.title' 
  } 
});

And we end up with this...

<ul class='contacts'>  
  <li class='contact'>
    <span class='name'>Hello my name is <span class='firstAndLast'>hij1nx</span></span>  
    <p class='title'>code slayer</p>
  </li>
  <li class='contact'>
    <span class='name'>Hello my name is <span class='firstAndLast'>tmpvar</span></span>  
    <p class='title'>code pimp</p>
  </li>  
</ul>  

Weld is like template antimatter for Javascript. It is the antithesis of most templating technology. There is no special sugar required to add data into your markup. And best of all it works in the browser and on your node.js server! In the end we get more readable presentation, markup and decision making code that is maintainable by developers with more varying skill sets.


How do I do X with Weld?

Checkout the project here on github, developed by hij1nx and tmpvar of the Nodejitsu team.

If you want to learn more about JSDOM, go here it's an awesome project.