JS Template Engines Performance (v31)

Revision 31 of this benchmark created by Heavensrevenge on


Description

Preparation HTML

<script src="https://code.jquery.com/jquery-git2.js"></script>
<script src="http://rawgithub.com/eugenioclrc/handlehash.js/master/HandleHash.js"></script>

<script src="https://rawgithub.com/danactive/js-template-engines-performance/master/lib/underscore-1.4.4.min.js"></script>

<script src="https://rawgithub.com/danactive/js-template-engines-performance/master/lib/mustache-0.7.2.js"></script>

<script src="https://rawgithub.com/danactive/js-template-engines-performance/master/lib/handlebars.1.0.0-rc.3.js"></script>

<script src="https://rawgithub.com/danactive/js-template-engines-performance/master/lib/kendo.core.min.2013.1.319.js"></script>

<script src="https://rawgithub.com/danactive/js-template-engines-performance/master/lib/hogan-2.0.0.js"></script>

<script src="https://jsmart.googlecode.com/files/smart-2.9.min.js"></script>

<script src="http://paularmstrong.github.io/swig/js/swig.min.js"></script>

<script src="http://jlongster.github.io/nunjucks/files/nunjucks.min.js"></script>
<script src="https://rawgithub.com/olado/doT/master/doT.js"></script>
<script src="http://gsf.github.io/whiskers.js/whiskers.min.js"></script>
<script src="http://qatrix.com/js/qatrix-1.1.min.js"></script>

<!--External Template Definitions-->
<script type="text/x-kendo-template" id="kendoUIextTemplate"><div><h1 class='header'>#= data.header #</h1><h2 class='header2'>#= data.header2 #</h2><h3 class='header3'>#= data.header3 #</h3><h4 class='header4'>#= data.header4 #</h4><h5 class='header5'>#= data.header5 #</h5><h6 class='header6'>#= data.header6 #</h6><ul class='list'># for (var i = 0, l = data.list.length; i < l; i++) { #<li class='item'>#= data.list[i] #</li># } #</ul></div></script>


<script id="test_tpl" type="text/x-jsmart-tmpl"> 
<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'>{foreach from=$list item=list_item}<li class='item'>{$list_item}</li>{/foreach}</ul></div></script>


<script>
    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']
    };


    handleHashTemplate = HandleHash.build("<div><h1>{#=data.header#}</h1><h2 class='header2'>{#=data.header2 #}</h2><h3 class='header3'>{#= data.header3 #}</h3><h4 class='header4'>{#= data.header4 #}</h4><h5 class='header5'>{#= data.header5 #}</h5><h6 class='header6'>{#= data.header6 #}</h6><ul class='list'>{#for(data.list,item) #}<li class='item'>{#= item #}</li>{#endfor #</ul></div>");


    window.nunjucksTemplate = "<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>{% endfor %}</ul></div>";

    window.nunjucksCompiledTemplate = new nunjucks.Template(nunjucksTemplate, true);


    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.mustacheCompiledTemplate = Mustache.compile(mustacheTemplate);


    window.underscoreTemplate = _.template("<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.underscoreTemplateEach = _.template("<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, function(item){ %><li class='item'><%= item %></li><% }); %></ul></div>");


    window.underscoreTemplateEachCached = _.memoize(_.template("<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, function(item){ %><li class='item'><%= item %></li><% }); %></ul></div>"), function (v) {
        return v
    });

    window.underscoreTemplateCached = _.memoize(_.template("<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>"), function (v) {
        return v
    });



    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'>{{#each list}}<li class='item'>{{this}}</li>{{/each}}</ul></div>");



    window.swigTemplate = "<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>{% endfor %}</ul></div>";

    window.swigPrecompiledTemplate = swig.compile(swigTemplate);



    Handlebars.template((function(){var a=Handlebars.template,b=Handlebars.templates=Handlebars.templates||{};b["template-handlebars.html"]=a(function(a,b,c,d,e){function k(a,b){var c="";return c+="<li class='item'>"+i(typeof a===h?a.apply(a):a)+"</li>",c}this.compilerInfo=[2,">= 1.0.0-rc.3"],c=c||a.helpers,e=e||{};var f="",g,h="function",i=this.escapeExpression,j=this;f+="<div><h1 class='header'>",(g=c.header)?g=g.call(b,{hash:{},data:e}):(g=b.header,g=typeof g===h?g.apply(b):g),f+=i(g)+"</h1><h2 class='header2'>",(g=c.header2)?g=g.call(b,{hash:{},data:e}):(g=b.header2,g=typeof g===h?g.apply(b):g),f+=i(g)+"</h2><h3 class='header3'>",(g=c.header3)?g=g.call(b,{hash:{},data:e}):(g=b.header3,g=typeof g===h?g.apply(b):g),f+=i(g)+"</h3><h4 class='header4'>",(g=c.header4)?g=g.call(b,{hash:{},data:e}):(g=b.header4,g=typeof g===h?g.apply(b):g),f+=i(g)+"</h4><h5 class='header5'>",(g=c.header5)?g=g.call(b,{hash:{},data:e}):(g=b.header5,g=typeof g===h?g.apply(b):g),f+=i(g)+"</h5><h6 class='header6'>",(g=c.header6)?g=g.call(b,{hash:{},data:e}):(g=b.header6,g=typeof g===h?g.apply(b):g),f+=i(g)+"</h6><ul class='list'>",g=c.each.call(b,b.list,{hash:{},inverse:j.noop,fn:j.program(1,k,e),data:e});if(g||g===0)f+=g;return f+="</ul></div>",f})})());

    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.doTtemplate2 = doT.compile("<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'>{{~it.list :value:index}}<li class='item'>{{=value}}</li>{{~}}</ul></div>", {
        append: true
    });

    window.whiskersRender = whiskers.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'>{{for item in list}}<li class='item'>{{item}}</li>{{/for}}</ul></div>");

    //Resig Template Function (modified to support ')
    function tmpl(str) {
        var strFunc =
            "var p=[];" +
            "with(obj){p.push('" +

        str.replace(/[\r\t\n]/g, " ")
            .replace(/'(?=[^#]*#>)/g, "\t")
            .split("'").join("\\'")
            .split("\t").join("'")
            .replace(/<#=(.+?)#>/g, "',$1,'")
            .split("<#").join("');")
            .split("#>").join("p.push('") + "');}return p.join('');";

        return new Function("obj", strFunc);
    }

    window.resig = tmpl("<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>");

    //Resig modified template function (no "with" block)
    function tmpl2(str) {
        var strFunc =
            "var o='';" +
            "o='" +
            str.replace(/[\r\t\n]/g, " ")
            .replace(/'(?=[^#]*#>)/g, "\t")
            .split("'").join("\\'")
            .split("\t").join("'")
            .replace(/<#=(.+?)#>/g, "'+($1)+'")
            .split("<#").join("';")
            .split("#>").join("o+='") + "';return o;";

        return new Function("data", strFunc);
    }

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

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

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

    //Use external template definition
    window.kendoUIAlt1 = kendo.template($("#kendoUIextTemplate").html());
    window.kendoUIAlt2 = kendo.template($("#kendoUIextTemplate").html(), {
        useWithBlock: false
    });


    window.hoganCompile = Hogan.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'>{{{.}}}</li>{{/list}}</ul></div>");



    window.jsmartObj = new jSmart(document.getElementById('test_tpl').innerHTML);
    window.jsmartFetch = function (data) {
        jsmartObj.fetch(data);
    };
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
mustache.js
Mustache.render(mustacheTemplate, sharedVariables);
ready
underscore.js
underscoreTemplate(sharedVariables);
ready
handlebar.js
handlebarsTemplate(sharedVariables);
ready
handlebar.js (precompiled)
Handlebars.templates["template-handlebars.html"](sharedVariables);
ready
Hogan.js
hoganCompile.render(sharedVariables)
ready
Kendo UI Templates (Default)
kendouiTemplate(sharedVariables);
ready
Kendo UI Templates (No "with" block)
kendouiTemplate2(sharedVariables);
ready
Resig Micro Templates (modified)
resig(sharedVariables);
ready
Resig Micro Templates (No "with" block)
resig2(sharedVariables);
ready
jsmart
jsmartFetch(sharedVariables);
ready
Swig
swig.render(swigTemplate, sharedVariables);
ready
Swig Precompiled
swigPrecompiledTemplate(sharedVariables);
ready
underscore.js (_.each)
underscoreTemplateEach(sharedVariables);
ready
Mustache (compiled)
mustacheCompiledTemplate(sharedVariables);
ready
Nunjucks (compiled)
nunjucksCompiledTemplate.render(sharedVariables);
ready
Nunjucks
nunjucks.renderString(nunjucksTemplate, sharedVariables);
ready
HandleHash
handleHashTemplate(sharedVariables);
ready
underscore each cached
underscoreTemplateEachCached(sharedVariables);
ready
underscore for cached
underscoreTemplateCached(sharedVariables);
ready
doT.js
doTtemplate(sharedVariables);
ready
doT.js 2
doTtemplate2(sharedVariables);
ready
Whiskers.js
whiskersRender(sharedVariables);
ready

Revisions

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