A Comprehensive Guide to Using doT.js

doT.js is a minimalistic yet powerful JavaScript templating engine designed for Node.js and browsers. Known for being extremely fast and concise, doT.js emphasizes performance, especially in environments like V8 and Node.js. It is a dependency-free library with only 120 lines of code, making it a lean and efficient choice for rendering dynamic content. This post will cover everything you need to know to start using doT.js, including installation, syntax, and real-world examples.


Why Choose doT.js?

doT.js was created to provide a fast and easy-to-use templating engine that works well in both server-side (Node.js) and client-side environments. Here are some reasons to consider it:

  • Performance: doT.js is one of the fastest template engines available.

  • No Dependencies: It is lightweight, without external dependencies.

  • Customizable: You can adjust delimiters and use features like runtime and compile-time evaluation.

  • Flexibility: Works in both logic-less mode and with full logic, making it adaptable for different use cases.

Key Features

  • No dependencies (120 LOC)

  • Blazing fast performance

  • Custom delimiters for flexibility

  • Runtime & compile-time evaluation

  • Partials and include support

  • Conditionals and iterators for dynamic logic

  • Encoding to avoid XSS vulnerabilities

  • Whitespace control (strip or preserve)

  • Streaming-friendly


Installation

For Node.js

You can install doT.js using npm:

npm install dot

Once installed, require it in your code:

const doT = require('dot');

For Browsers

Simply include the JavaScript file in your HTML file:

<script src="doT.js"></script>

Basic Usage

To begin using doT.js, you first need to compile a template and then render it with data.

1. Compile a Template

const templateFunction = doT.template("<h1>Hello, {{=it.name}}</h1>");

{{=it.name}} is used to interpolate the name property from the provided data.

2. Render the Template with Data

const result = templateFunction({ name: "World" });
console.log(result); // <h1>Hello, World</h1>

doT.js Syntax and Delimiters

By default, doT.js uses the following delimiters:

  • {{ }}: for evaluation (JavaScript logic)

  • {{= }}: for interpolation (inserting variables)

  • {{! }}: for interpolation with encoding (to prevent XSS)

  • {{# }}: for compile-time evaluation or partials

  • {{## #}}: for compile-time defines

  • {{? }}: for conditionals

  • {{~ }}: for array iteration

You can modify these delimiters by adjusting doT.templateSettings.

Conditional Rendering

const conditionTemplate = doT.template("{{? it.show }}Hello, {{=it.name}}{{?}}");
console.log(conditionTemplate({ show: true, name: "Alice" })); // "Hello, Alice"
console.log(conditionTemplate({ show: false, name: "Bob" }));  // ""

{{? it.show }} checks if the show property is true. If so, the text will be displayed; otherwise, it remains hidden.

Array Iteration

const listTemplate = doT.template("<ul>{{~it.items :item:index}}<li>{{=item}}</li>{{~}}</ul>");
const result = listTemplate({ items: ["Item 1", "Item 2", "Item 3"] });
console.log(result); // <ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>

{{~it.items :item:index}} iterates over the items array, rendering each item inside a <li> tag.


Advanced Features

Compile-Time vs Runtime Evaluation

Compile-time evaluation can improve performance when rendering static content, or when including partials like headers or footers that don't change frequently.

Compile-Time Example:

const headerTemplate = doT.template("{{#def.header}}<h1>{{=it.title}}</h1>{{#def.footer}}", null, { header: "<header>Header</header>", footer: "<footer>Footer</footer>" });
const result = headerTemplate({ title: "Welcome" });
console.log(result); // <header>Header</header><h1>Welcome</h1><footer>Footer</footer>

Custom Delimiters

If you need to use custom delimiters, you can modify doT.templateSettings.

doT.templateSettings = {
  evaluate: /\[\[([\s\S]+?)\]\]/g,
  interpolate: /\[\[=([\s\S]+?)\]\]/g,
};

Now, instead of using {{ }}, you can use [[ ]].

Partials Support

Partials are useful for reusing common parts of a template, like headers or footers. You can define partials using {{#def}} syntax.

Precompiling Templates for Production

You can precompile templates for performance optimization. This feature is especially useful when deploying in Node.js or for client-side rendering in browsers.

const dots = require("dot").process({ path: "./views" });
const render = require('./views/mytemplate');
console.log(render({ foo: "Hello, world" }));

Examples

Here are additional samples based on the existing DoT.js template structure.

<div class="user-profile">
  {{? it.isLoggedIn }}
  <h3>Welcome, {{=it.username}}!</h3>
  {{? it.showEmail}}<p>Email: {{=it.email}}</p>{{?}}
  {{? it.showAddress}}<p>Address: {{=it.address}}</p>{{?}}
  <a href="/logout" class="logout-btn">Logout</a>
  {{??}}
  <p>You are not logged in.</p>
  <a href="/login" class="login-btn">Login</a>
  {{?}}
</div>

This template dynamically checks if a user is logged in and optionally displays their email and address if available. If the user is not logged in, it shows a login button.

<div class="product-list">
  {{~ it.products :product}}
    <div class="product-item">
      <h4>{{=product.name}}</h4>
      <p>Price: ${{=product.price}}</p>
      {{? product.isDiscounted}}
      <p>Discount: {{=product.discount}}%</p>
      {{?}}
      <a href="/product/{{=product.id}}" class="view-product">View Product</a>
    </div>
  {{~}}
</div>

This template loops through a list of products and shows the product name and price. If a product is discounted, it displays the discount percentage.

<div class="blog-post">
  <h2>{{=it.title}}</h2>
  <p>{{=it.content}}</p>
  {{? it.tags.length > 0}}
  <ul class="tags">
    {{~ it.tags :tag}}
      <li>{{=tag}}</li>
    {{~}}
  </ul>
  {{?}}
</div>

A blog post template displays the title and content. If there are tags associated with the post, it renders a list of tags.

doT.js is a lightweight, fast, and flexible templating engine, ideal for developers looking to optimize both server-side and client-side rendering. Whether you're working on a simple app or need a high-performance solution for rendering dynamic content, doT.js offers powerful features that can be customized to fit your needs. From compile-time evaluation to runtime flexibility, this templating engine can handle a wide range of use cases with minimal setup and blazing-fast performance.

Happy coding with doT.js!

10
Subscribe to my newsletter

Read articles from Nirmal Sankalana directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nirmal Sankalana
Nirmal Sankalana