JavaScript template language shootoff - precompilation (v319)

Revision 319 of this benchmark created by Jens Roland on


Description

A comparison of the precompilation step for some JavaScript templating engines, when used for multilevel templates:

Preparation HTML

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

<script src="http://cdn.kendostatic.com/2011.2.804/js/kendo.all.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>
   <# for (var ix = 0, l = data.lists.length; ix < l; ix++) {
      var listsElem = data.lists[ix];
   #>
      <h1><#= listsElem.title #></h1>
      <ul class='list'>
         <# for (var mx = 0, n = listsElem.listitem.length; mx < n; mx++) {
            var listitemElem = listsElem.listitem[mx];
         #>
         <li class='item'><#= listitemElem.i #></li>
         <# } #>
      </ul>
   <# } #>
</div>
</script>

<script>
window.variabledata_tree = {
    header: "Header",
    header2: "Header2",
    header3: "Header3",
    header4: "Header4",
    header5: "Header5",
    header6: "Header6",
    lists: [
        {
            title: "Long list",
            listitem: [{i:'1'}, {i:'2'}, {i:'3'}, {i:'4'}, {i:'5'}, {i:'6'}, {i:'7'}, {i:'8'}]
        },
        {
            title: "Short list",
            listitem: [{i:'A'}, {i:'B'}, {i:'C'}]
        }
    ]
};

  //Resig modified template function (no "with" block)
  function tmpl2(str) {
              var strFunc =
              "var p=[];" +
                          "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("data", strFunc);
          }
  

var T2={};
T2.Template = (function(){
        var t2c_sub = function(id,tmpls,parent) {
                var str = tmpls[id],
                        indexVar = '_'+id.replace('.','_'),
                        arrayVar = indexVar+'Arr',
                        elemVar = indexVar+'Elem',
                        strFunc = "';for (var "+indexVar+"=0, "+arrayVar+"="+parent+"."+id+"; "+indexVar+"<"+arrayVar+".length; "+indexVar+"++) {var "+elemVar+"="+arrayVar+"["+indexVar+"]; p+='" +
                str
                        .replace(/[\r\t\n]/g, " ")
                        .replace(/'(?=[^#]*#\})/g, "\t")
                        .split("'").join("\\'")
                        .split("\t").join("'")
                        .replace(/\{=@(.+?)\}/g, function(a,b){ return t2c_sub(b,tmpls,elemVar); })
                        .replace(/\{=(.+?)\}/g, "'+"+elemVar+".$1+'")
                        .split("{#").join("';")
                        .split("#}").join("p+='")
                        + "';}p+='";
                return strFunc;
        };

        var exports = {};

        exports.precompile = function(tmpls) {
                var str = tmpls['$'],
                        strFunc = "var p='';p+='" +
                str
                        .replace(/[\r\t\n]/g, " ")
                        .replace(/'(?=[^#]*#\})/g, "\t")
                        .split("'").join("\\'")
                        .split("\t").join("'")
                        .replace(/\{=@(.+?)\}/g, function(a,b){ return t2c_sub(b,tmpls,'data'); })
                        .replace(/\{=(.+?)\}/g, "'+data.$1+'")
                        .split("{#").join("';")
                        .split("#}").join("p+='")
                        + "';return p;";
                return new Function("data", strFunc);
        };

        return exports;
})();

</script>

Test runner

Ready to run.

Testing in
TestOps/sec
Resig Micro Templates (No "with" block)
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><# for (var ix = 0, l = data.lists.length; ix < l; ix++) {var listsElem = data.lists[ix];#><h1><#= listsElem.title #></h1><ul class='list'><# for (var mx = 0, n = listsElem.listitem.length; mx < n; mx++) {var listitemElem = listsElem.listitem[mx];#><li class='item'><#= listitemElem.i #></li><# } #></ul><# } #></div>");
ready
Kendo UI Templates (No "with" block)
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><# for (var ix = 0, l = data.lists.length; ix < l; ix++) {var listsElem = data.lists[ix];#><h1><#= listsElem.title #></h1><ul class='list'><# for (var mx = 0, n = listsElem.listitem.length; mx < n; mx++) {var listitemElem = listsElem.listitem[mx];#><li class='item'><#= listitemElem.i #></li><# } #></ul><# } #></div>", {useWithBlock:false});
ready
Kendo UI Templates (External Temp Def - No "with" block))
kendo.template($("#kendoUIextTemplate").html(), {useWithBlock:false});
 
ready
T2 template v5 (Resig+Kendo, w. loop sugar)
T2.Template.precompile({
    $:"<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>{=@lists}</div>",
    lists: "<h1>{=title}</h1><ul class='list'>{=@listitem}</ul>",
    listitem: "<li class='item'>{=i}</li>"
});
ready
T2 template v6 (Resig+Kendo, using JS blocks)
T2.Template.precompile({
    $:"<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>{#for (var _i = 0, m = data.lists.length; _i < m; _i++) {data.listsElem = data.lists[_i];#}<h1>{=listsElem.title}</h1><ul class='list'>{#for (var _j = 0, n = data.listsElem.listitem.length; _j < n; _j++) {data.listitemElem = data.listsElem.listitem[_j];#}<li class='item'>{=listitemElem.i}</li>{# } #}</ul>{# } #}</div>"
});
ready

Revisions

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