JavaScript template language shootoff

JavaScript performance comparison

Revision 564 of this test case created by Trevor Norris and last updated

Info

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 code

<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>
 

Preparation code output

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Mustache.js Template
var div = document.createElement('div');
div.innerHTML = Mustache.to_html(mustacheTemplate, sharedVariables);
 
pending…
Resig Micro-Templating.
var div = document.createElement('div');
div.innerHTML = resigTemplate(sharedVariables);
pending…
Creationix's Haml-js Template
var div = document.createElement('div');
div.innerHTML = hamlTemplate(sharedVariables);
pending…
Jade Template
var div = document.createElement('div');
div.innerHTML = jade.render(jadeTemplate, {
 locals: sharedVariables,
 filename: 'test.js',
 cache: true
});
pending…
JUP Template
var div = document.createElement('div');
div.innerHTML = JUP.html([sharedVariables], jupTemplate);
pending…
Underscore.js Template
var div = document.createElement('div');
div.innerHTML = underscoreTemplate(sharedVariables);
pending…
Eco Template
var div = document.createElement('div');
div.innerHTML = ecoTemplate(sharedVariables);
pending…
jQuery Templates
$.tmpl(jQueryTemplate, sharedVariables);
pending…
Handlebars.js
var div = document.createElement('div');
div.innerHTML = handlebarsTemplate(sharedVariables);
pending…
doT.js
var div = document.createElement('div');
div.innerHTML = doTtemplate(sharedVariables);
pending…
doU.js
var div = document.createElement('div');
div.innerHTML = doUtemplate(sharedVariables);
pending…
jQote2 direct
var div = document.createElement('div');
div.innerHTML = jqote2.call(sharedVariables, 0, 0, [sharedVariables], jqote2);
pending…
Orange-J
var div = document.createElement('div');
div.innerHTML = $.snippet("test1", sharedVariables);
pending…
NoHtml
$(noHtmlTemplate(sharedVariables));
pending…
jqml
jqml(jqmlTemplate);
pending…
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>';
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment