The fastest + concise javascript template engine
for node.js and browsers

by Laura Doktorova, MIT Licence


Templates are everywhere!

  • Servers
  • Clients
  • HTML
  • SVG
  • Emails
  • CSS
  • JavaScript!
  • e.t.c.
  • e.t.c.
  • e.t.c.

A lot of JavaScript templates now

  • doT.js
  • mustache.js
  • jQote2.js
  • underscore.js
  • hogan.js
  • jade.js
  • dust.js
  • less.js
  • jsRender.js
  • etc.
  • etc.
  • etc.
Visit template chooser by Garann to help you choose

... choose doT.js! :)

  • no dependencies
  • 120 loc, 1.3K minified and gzipped
  • extremely fast
  • use it as logic-less or with logic, it is up to you
  • custom delimiters
  • composited
  • control whitespace - strip or preserve
  • works on any text just make sure your text format does not conflict with default delimiters. If it does, change delimiters

How doT.js works

  • Compiles template into a JavaScript function
  • Produced functions have no dependencies on doT - you can precompile your templates and ship JavaScript without doT.

Why use a fast engine?

  • Shopping bill paradox - small numbers add up
  • Do not want to slow down Node.js event loop
  • Why not?

How to measure performance?

  • JSPerf is your friend!
  • (JSLitmus too)

Templates: performance benchmarking

Some things to pay attention to when looking at benchmarks:

  • compilation speed
  • caching
  • render speed
  • updating the DOM (if on client)
  • size and complexity of the template
JSPerf benchmarks

Why is doT.js fast?

  • Does not use with statement
  • Does not use push/join, instead uses string concatenation
  • Trims all excess from the generated function
  • Statically compiles partials
  • Fast routine for HTML encoding

Default tags

  • {{ }} runtime evaluation
  • {{= }} runtime interpolation
  • {{# }} compile-time evaluation
  • {{## #}} inline subtemplates
  • {{? }} conditionals
  • {{~ }} array iterators
  • {{! }} encoding


    Compile-time defines (def)

    doT.template compiles it into




    • 1. Compile template function

      var template = doT.template("<h1>Hi {{}}!</h1>");
    • 2. Use template function as many times as you like

      var resultText = template({foo: 'there'});


    doT.templateSettings = {
      evaluate:    /\{\{([\s\S]+?)\}\}/g,
      interpolate: /\{\{=([\s\S]+?)\}\}/g,
      encode:      /\{\{!([\s\S]+?)\}\}/g,
      use:         /\{\{#([\s\S]+?)\}\}/g,
      define:      /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
      conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
      iterate:     /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
      varname: 'it',
      strip: true,
      append: true,
      selfcontained: false

    Compilation function

    • Call this function to compile your template into a function.

      doT.template(template, settings, def)
    • For express compatibility there is also

      doT.compile(template, def)
    where def is a dictionary of defines and subtemplates to use

    Compositing with inline templates

    • 1. Define inline subtemplates

          Hi {{}}!
          {{#def.content || ''}}
    • 2. Use it anywhere as many times as you want


    This is illustrated in the playground

    Compositing with external subtemplates

    Some examples of external templates:

    • local files
    • remote resources
    • DOM nodes

    How: compositing with external subtemplates

    • Use you favourite methods to obtain the template text and add to the dictionary object

      var def = {
          header: $('header_t').html(),
          footer: $('footer_t').html()

      Pass this object as def parameter when compiling your templates

    Alternatevely, you could use a global dictionary instead of def parameter

    You can also do this

    • {{ function gradient(from, to) { }}
      background: {{=from}};
      background:-webkit-gradient(linear, left top, left bottom, from({{=from}}), to({{=to}}));
      background:-moz-linear-gradient(top, {{=from}}, {{=to}});
      {{ } }}
    • .note {
          {{ gradient("#FFFCD1","#FFF9B1"); }}


    • {{~}} iterator does not support object iteration
    • Compile time 'use' does not prevent infinite recursion, relies on developer to make sure they have a stop
    • Defines are assigned once and there is no #undef-like operation

    Fork doT.js on github
    1 /