BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News New Template DSL Tempura Focuses on Parsing Speed and Size

New Template DSL Tempura Focuses on Parsing Speed and Size

This item in japanese

Bookmarks

Luke Edwards recently released Tempura, a lightweight template DSL designed to achieve fast parsing speeds. Like other static site generators’ templating languages (e.g, Hugo’s shortcodes, Hexo’s tag plugins), Tempura also features custom blocks for user-defined template directives. While Tempura’s primary use case is to generate HTML for web applications, it can be used in any context where a template DSL adds value vs. using JavaScript.

The Tempura documentation details four characteristics of interest. The entire templating library is slightly below 1.3 KB; is faster than similar template DSLs according to one benchmark; has syntax similar to that of Handlebars; and lets users define custom templating directives.

An example of syntax is as follows:

{{! expected props to receive }}
{{#expect title, items }}

{{! inline variables }}
{{#var count = items.length }}
{{#var suffix = count === 1 ? 'task' : 'tasks' }}

{{#if count == 0}}
  <p>You're done! </p>
{{#else}}
  <p>You have {{{ count }}} {{{ suffix }}} remaining!</p>

  {{#if count == 1}}
    <small>Almost there!</small>
  {{#elif count > 10}}
    <small>... you must be <em>fried</em> </small>
  {{#else}}
    <small>You've got this </small>
  {{/if}}

  <ul>
    {{#each items as todo}}
      <li>{{ todo.text }}</li>
    {{/each}}
  </ul>
{{/if}}

The expect tag introduces the parameters that are used in the template. The each tag indicates a for loop. The {{ and }} mustache delimiters enclose template directives that apply to the text delimited by the closing directive tag (e.g., #each is closed with /each).

Tempura compiles templates either to a JavaScript function or to a string that contains scripting code (ES Module or CommonJS format), the latter being ideal for bundlers.

The following sample code showcases the output of the previously reproduced template compiled to a JavaScript function:

let render = compile(template);
console.log(typeof render); //=> "function"
render({
  title: 'Reminders',
  items: [
    { id: 1, text: 'Feed the doggo' },
    { id: 2, text: 'Buy groceries' },
    { id: 3, text: 'Exercise, ok' },
  ]
});
//=> "<p>You have 3 tasks remaining!</p>\n"
//=> + "<small>You've got this </small>\n\n"
//=> + "<ul>\n"
//=> + "  <li>Feed the doggo</li>\n"
//=> + "  <li>Buy groceries</li>\n"
//=> + "  <li>Exercise, ok</li>\n"
//=> + "</ul>"

Template DSLs address the need to provide a better template developer experience or a simpler language to profane users. In a typical web application, a web page is a sequence of HTML markups that are parameterized by page-specific data. That parameterization can be described with a standard function from a Turing-complete language like JavaScript, a function which accepts the page-specific parameters and produces the desired markup. Alternatively, in most cases, that function can be expressed with a template DSL with simpler syntax that fits better the template user needs.

For instance, web designers who know HTML (but are not proficient in JavaScript) are more likely to read Vue templates without prior Vue-specific training. This allows users who are not programmers to also participate in the software development process.

Template DSLs are necessarily less expressive than general-purpose, Turing-complete languages. In particular, template DSLs cannot express arbitrary computations. They can however be designed to be easier to parse and reason about from both a computer and human user perspective. Front-end frameworks like Vue, Svelte, or Solid leverage for instance their template syntax to optimize web pages’ DOM updates based on changes in the value of the template parameters.

The speed with which the compiled template generates output may be valuable. For instance, in a server-side rendering (SSR) context, faster output generation means less latency for the web application user. It also may result in more requests per unit of time being processed by the server and possibly lower server costs.

Rate this Article

Adoption
Style

BT