JavaScript template language shootoff

JavaScript performance comparison

Revision 350 of this test case created

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.

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

1 comment

Grant Husbands commented :

JUP templates in fact cannot perform this benchmark, as they can only show properties of entries, and the integers in the list don't have such. Also, they offer no precompilation and no looping constructs. I'll create a version without such.

Add a comment