JavaScript template language shootoff (v564)

Revision 564 of this benchmark created by Trevor Norris on


Description

A brief comparison of some JavaScript templating engines on a short template: 6 header tags, and 10 list items.

Added doT, doU and jQote2 to benchmarks.

Added jqml to benchmarks.

Results that output strings are attached using innerHTML to discover actual DOM performance.

noHtml should be using reduce(). Not forEach, which doesn't return anything.

Preparation HTML

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<script src="http://documentcloud.github.com/underscore/underscore.js"></script>

<script src="http://github.com/hij1nx/JUP/raw/master/lib/jup.js"></script>

<script src="http://github.com/janl/mustache.js/raw/master/mustache.js"></script>

<script src="https://github.com/downloads/paul/handlebars.js/handlebars.js"></script>

<script src="http://gist.github.com/raw/550881/29bb186167079c0b33ab6e9d50d779f37860cfa4/micro.js"></script>

<script src="http://github.com/creationix/haml-js/raw/master/lib/haml.js"></script>

<script src="http://gist.github.com/raw/550723/12d176698628e30a1df398c7ac7aea93924e1294/jade.js"></script>

<script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js"></script>
<script src="http://sstephenson.github.com/eco/dist/eco.js"></script>

<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>

<script src="https://github.com/olado/doT/raw/master/doT.js"></script>

<script src="https://github.com/olado/doT/raw/master/doU.js"></script>

<script src="https://raw.github.com/mobz/nohtml/master/src/jquery-nohtml.js"></script>

<script src="http://github.com/aefxx/jQote2/raw/69b2053a13f5f180e696de9b3dba856a3c00678c/jquery.jqote2.js"></script>

<script src="https://raw.github.com/relativityboy/Orange-J/master/jquery.orange.js"></script>

<script src="https://raw.github.com/trevnorris/jqml/master/src/jqml.min.js"></script>

<script>
  window.mustacheTemplate = "<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{.}}</li>{{/list}}</ul></div>";

  window.handlebarsTemplate = Handlebars.compile("<div><h1 class='header'>{{header}}</h1><h2 class='header2'>{{header2}}</h2><h3 class='header3'>{{header3}}</h3><h4 class='header4'>{{header4}}</h4><h5 class='header5'>{{header5}}</h5><h6 class='header6'>{{header6}}</h6><ul class='list'>{{#list}}<li class='item'>{{this}}</li>{{/list}}</ul></div>");

  window.micro = "<div><h1 class='header'><%= header %></h1><h2 class='header2'><%= header2 %></h2><h3 class='header3'><%= header3 %></h3><h4 class='header4'><%= header4 %></h4><h5 class='header5'><%= header5 %></h5><h6 class='header6'><%= header6 %></h6><ul class='list'><% for (var i = 0, l = list.length; i < l; i++) { %><li class='item'><%= list[i] %></li><% } %></ul></div>";

  window.underscoreTemplate = _.template(micro);

  window.resigTemplate = tmpl(micro);

  window.sharedVariables = {
   header: "Header",
   header2: "Header2",
   header3: "Header3",
   header4: "Header4",
   header5: "Header5",
   header6: "Header6",
   list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
  };

  window.jupTemplate = ['div', ['h1',
  {
   'class': 'header'
  }, "{{header}}"],
   ['h2',
   {
    'class': 'header2'
   }, "{{header2}}"],
   ['h3',
   {
    'class': 'header3'
   }, "{{header3}}"],
   ['h4',
   {
    'class': 'header4'
   }, "{{header4}}"],
   ['h5',
   {
    'class': 'header5'
   }, "{{header5}}"],
   ['h6',
   {
    'class': 'header6'
   }, "{{header6}}"],
   ['ul',
   {
    'class': 'list'
   }, ['li',
   {
    'class': 'item'
   }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item'
    }, '{{list}}'],
    ['li',
    {
     'class': 'item}'
    }, '{{list}}']
   ]
  ];

  window.jqmlTemplate = ['div',
      ['h1', sharedVariables.header, {'class': 'header'}],
      ['h2', sharedVariables.header2, {'class': 'header2'}],
      ['h3', sharedVariables.header3, {'class': 'header3'}],
      ['h4', sharedVariables.header4, {'class': 'header4'}],
      ['h5', sharedVariables.header5, {'class': 'header5'}],
      ['h6', sharedVariables.header6, {'class': 'header6'}],
      (function() {
        var list = ['ul'];
        for (var i = 0; i < sharedVariables.list.length; i++) {
          list.push(['li', sharedVariables.list[i], {'class': 'item'}]);
        }
        return list;
      }())
    ];

  window.jadeTemplate = "div\n  h1.header!= header\n  h2.header2!= header2\n  h3.header3!= header3\n  h4.header4!= header4\n  h5.header5!= header5\n  h6.header6!= header6\n  ul.list\n    - each item in list\n      li.item!= item";

  window.hamlTemplate = Haml("%div\n  %h1.header= header\n  %h2.header2= header2\n  %h3.header3= header3\n  %h4.header4= header4\n  %h5.header5= header5\n  %h6.header6= header6\n  %ul.list\n    :each item in list\n      %li.item= item");

  window.ecoTemplate = eco("<div><h1 class='header'><%- @header %></h1><h2 class='header2'><%- @header2 %></h2><h3 class='header3'><%- @header3 %></h3><h4 class='header4'><%- @header4 %></h4><h5 class='header5'><%- @header5 %></h5><h6 class='header6'><%- @header6 %></h6><ul class='list'><% for item in @list: %><li class='item'><%- item %></li><% end %></ul></div>");

  window.jQueryTemplate = $.template(null, "<div><h1 class='header'>${header}</h1><h2 class='header2'>${header2}</h2><h3 class='header3'>${header3}</h3><h4 class='header4'>${header4}</h4><h5 class='header5'>${header5}</h5><h6 class='header6'>${header6}</h6><ul class='list'>{{each list}}<li class='item'>${$value}</li>{{/each}}</ul></div>");

  window.doTtemplate = doT.template("<div><h1 class='header'>{{= it.header }}</h1><h2 class='header2'>{{= it.header2 }}</h2><h3 class='header3'>{{= it.header3 }}</h3><h4 class='header4'>{{= it.header4 }}</h4><h5 class='header5'>{{= it.header5 }}</h5><h6 class='header6'>{{= it.header6 }}</h6><ul class='list'>{{ for (var i = 0, l = it.list.length; i < l; i++) { }}<li class='item'>{{= it.list[i] }}</li>{{ } }}</ul></div>");

  window.doUtemplate = doU.template("<div><h1 class='header'>{{= it.header }}</h1><h2 class='header2'>{{= it.header2 }}</h2><h3 class='header3'>{{= it.header3 }}</h3><h4 class='header4'>{{= it.header4 }}</h4><h5 class='header5'>{{= it.header5 }}</h5><h6 class='header6'>{{= it.header6 }}</h6><ul class='list'>{{ for (var i = 0, l = it.list.length; i < l; i++) { }}<li class='item'>{{= it.list[i] }}</li>{{ } }}</ul></div>");

  window.noHtmlTemplate = function(data){ return {tag: "DIV",children:[{tag:"H1",cls:"header",text:data.header},{tag:"H2",cls:"header2",text:data.header2},{tag:"H3",cls:"header3",text:data.header3},{tag:"H4",cls:"header4",text:data.header4},{tag:"H5",cls:"header5",text:data.header5},{tag:"H6",cls:"header6",text:data.header6},{tag:"UL",cls:"list",children:data.list.reduce(function(p,item){p.push({tag:"LI",cls:"item",text:item}); return p;},[])}]}};

  window.jqote_tmpl = "<div><h1 class='header'><%= this.header %></h1><h2 class='header2'><%= this.header2 %></h2><h3 class='header3'><%= this.header3 %></h3><h4 class='header4'><%= this.header4 %></h4><h5 class='header5'><%= this.header5 %></h5><h6 class='header6'><%= this.header6 %></h6><ul class='list'><% for (var n = 0, l = this.list.length; n < l; n++) { %><li class='item'><%= this.list[n] %></li><% } %></ul></div>";

  window.jqote2 = $.jqotec(jqote_tmpl);

  $.addSnippet("test1", "<div><h1 class='header'>{header}</h1><h2 class='header2'>{header2}</h2><h3 class='header3'>{header3}</h3><h4 class='header4'>{header4}</h4><h5 class='header5'>{header5}</h5><h6 class='header6'>{header6}</h6><ul class='list'>{list[]}<li class='item'>{val}</li>{[]list}</ul></div>");
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
Mustache.js Template
var div = document.createElement('div');
div.innerHTML = Mustache.to_html(mustacheTemplate, sharedVariables);
 
ready
Resig Micro-Templating.
var div = document.createElement('div');
div.innerHTML = resigTemplate(sharedVariables);
ready
Creationix's Haml-js Template
var div = document.createElement('div');
div.innerHTML = hamlTemplate(sharedVariables);
ready
Jade Template
var div = document.createElement('div');
div.innerHTML = jade.render(jadeTemplate, {
 locals: sharedVariables,
 filename: 'test.js',
 cache: true
});
ready
JUP Template
var div = document.createElement('div');
div.innerHTML = JUP.html([sharedVariables], jupTemplate);
ready
Underscore.js Template
var div = document.createElement('div');
div.innerHTML = underscoreTemplate(sharedVariables);
ready
Eco Template
var div = document.createElement('div');
div.innerHTML = ecoTemplate(sharedVariables);
ready
jQuery Templates
$.tmpl(jQueryTemplate, sharedVariables);
ready
Handlebars.js
var div = document.createElement('div');
div.innerHTML = handlebarsTemplate(sharedVariables);
ready
doT.js
var div = document.createElement('div');
div.innerHTML = doTtemplate(sharedVariables);
ready
doU.js
var div = document.createElement('div');
div.innerHTML = doUtemplate(sharedVariables);
ready
jQote2 direct
var div = document.createElement('div');
div.innerHTML = jqote2.call(sharedVariables, 0, 0, [sharedVariables], jqote2);
ready
Orange-J
var div = document.createElement('div');
div.innerHTML = $.snippet("test1", sharedVariables);
ready
NoHtml
$(noHtmlTemplate(sharedVariables));
ready
jqml
jqml(jqmlTemplate);
ready
Native
var div = document.createElement('div');
div.innerHTML = '<div>'
                   +    '<h1 class="header">'+sharedVariables.header+'</h1>'
                   +    '<h2 class="header2">'+sharedVariables.header2+'</h2>'
                   +    '<h3 class="header3">'+sharedVariables.header3+'</h3>'
                   +    '<h4 class="header4">'+sharedVariables.header4+'</h4>'
                   +    '<h5 class="header5">'+sharedVariables.header5+'</h5>'
                   +    '<h6 class="header6">'+sharedVariables.header6+'</h6>'
                   +    '<ul class="list">'
                   +    (function () {
                var res = '';
                for (var i = 0, l = sharedVariables.list.length; i < l; i++) { res += '<li class="item">'+sharedVariables.list[i]+'</li>'; }
                return res;
            })()
                   +    '</ul>'
                   +'</div>';
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.