JS Template Engines Performance (v33)

Revision 33 of this benchmark created by Heavensrevenge on


Description

Preparation HTML

<!-- Targeted DIV -->
<div id="target" style="display: none;"></div>

<!-- Libraries -->
<script src="https://code.jquery.com/jquery-git2.js"></script>
<script src="https://rawgithub.com/eugenioclrc/handlehash.js/master/HandleHash.js"></script>
<script src="https://documentcloud.github.io/underscore/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.2/mustache.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.2.1/handlebars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hogan.js/2.0.0/hogan.min.js"></script>
<script src="https://rawgithub.com/olado/doT/master/doT.js"></script>
<script src="https://gsf.github.io/whiskers.js/whiskers.min.js"></script>
<script src="https://qatrix.com/js/qatrix-1.1.min.js"></script>
<script src="https://rawgithub.com/premasagar/875670/raw/d52752ead19a4eebc7237602438ae08a2541a5b5/tim-lite-cached-min.js"></script>

Setup

sharedVariables = {
            header: "Header",
            header2: "Header 2",
            header3: "Header 3",
            header4: "Header 4",
            header5: "Header 5",
            header6: "Header 6",
            list: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
        };
    
    var element = document.getElementById('target');
    
        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>");
    
    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>");
    
    
        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>";
    
    
        mustacheCompiledTemplate = Mustache.compile(mustacheTemplate);
    
    
        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>");
    
    
        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>");
    
    
        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
        });
    
        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
        });
    
    
    
        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>");
    
    
        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>");
    
        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
        });
    
        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);
        }
    
        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);
        }
    
        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>");

Test runner

Ready to run.

Testing in
TestOps/sec
mustache.js
element.innerHTML = Mustache.render(mustacheTemplate, sharedVariables);
ready
underscore.js
element.innerHTML = underscoreTemplate(sharedVariables);
ready
handlebar.js
element.innerHTML = handlebarsTemplate(sharedVariables);
ready
Hogan.js
element.innerHTML = hoganCompile.render(sharedVariables);
ready
Resig Micro Templates (modified)
element.innerHTML = resig(sharedVariables);
ready
Resig Micro Templates (No "with" block)
element.innerHTML = resig2(sharedVariables);
ready
underscore.js (_.each)
element.innerHTML = underscoreTemplateEach(sharedVariables);
ready
Mustache (compiled)
element.innerHTML = mustacheCompiledTemplate(sharedVariables);
ready
HandleHash
element.innerHTML = handleHashTemplate(sharedVariables);
ready
underscore each cached
element.innerHTML = underscoreTemplateEachCached(sharedVariables);
ready
underscore for cached
element.innerHTML = underscoreTemplateCached(sharedVariables);
ready
doT.js
element.innerHTML = doTtemplate(sharedVariables);
ready
doT.js 2
element.innerHTML = doTtemplate2(sharedVariables);
ready
Whiskers.js
element.innerHTML = whiskersRender(sharedVariables);
ready

Revisions

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