doT.js
The fastest + concise javascript template engine
for node.js and browsers
https://github.com/olado/doT
by Laura Doktorova, MIT Licence
@olado http://bebedo.comTemplates 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.
... 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
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
Template
Compile-time defines (def)
doT.template compiles it into
Data
Result
Basics
-
1. Compile template function
var template = doT.template("<h1>Hi {{=it.foo}}!</h1>");
-
2. Use template function as many times as you like
var resultText = template({foo: 'there'});
Settings
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 useCompositing with inline templates
-
1. Define inline subtemplates
{{##def.myinlinepiece: Hi {{=it.name}}! {{#def.content || ''}} #}}
-
2. Use it anywhere as many times as you want
{{#def.myinlinepiece}}
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"); }} }
Disclaimers
- {{~}} 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