The client-side templating throwdown: mustache, handlebars, dust.js, and more

January 17, 2012

In a previous post, we told you how LinkedIn is dumping server-side templates in favor of client-side templates. We've gotten lots of great feedback that we'll discuss in future posts, but today, we'll focus on one question that was especially popular:

How did LinkedIn pick dust.js as its client-side templating solution?

In the following blog post, we'll outline the requirements we had, the evaluation process, and the results.

The candidates

Client side templating options

The open source community has created a huge number of client-side templating solutions. When we did our initial research, we came up with a list of 26 templating technologies. We eliminated 8 right off the bat, as they were either abandoned projects or wholly lacking any documentation or community usage, making it nearly impossible to properly test them out.

This left us with 18 templating technologies to evaluate. We found that these could be broken down into two general categories: embedded JavaScript and logic-less.

Embedded JavaScript Templates

These templating options allow you to embed regular JavaScript code directly within the template, an approach similar to ERBs.

  1. underscore.js
  2. Jade
  3. haml-js
  4. jQote2
  5. doT
  6. Stencil
  7. Parrot
  8. Eco
  9. EJS
  10. jQuery templates
  11. node-asyncEJS

Logic-less Templates

This group of templates follows the philosophy that there should be little to no logic in your templates. They do not allow arbitrary JavaScript code in the template. Instead, you must use the small set of constructs offered by the templating language itself, which, depending on the language, may include basic loops, conditionals, and partials.

  1. mustache
  2. dust.js
  3. handlebars
  4. Google Closure Templates
  5. Nun
  6. Mu
  7. kite

The Test

To pick between the 18 templating options, we assigned each option to a small team of front-end engineers and setup a test: render a (very simplified) LinkedIn profile.

The test: render a simplified profile

We gave each group two files to work with, which you can grab from this Github Gist:

The goal was to produce the exact output in profile.html using one of the templating technologies and the JSON data. We also included a few special requirements to force a slightly deeper dive:

  1. Write-once: make sure the same template can render on the server-side and client-side.
  2. Presentation logic: in the gray box at the top, the position labeled "Current" should be the first position in the sample JSON. The positions labeled "Past" should be positions 2-4. For each position listed under "Experience", assign different CSS classes for the odd and even numbered rows.
  3. Text formatting: anywhere you see a date, show the month name instead of the number (December instead of 12). The "summary" fields for each position should respect new lines: replace \n with <br/>.

The List

We gave each team a list of features to look for in their assigned templating solution. The idea was to fill out a score, from one (poor) to five (excellent), for each item:

  1. DRY: how DRY is the templating technology? is there support for code-reuse and partials?
  2. i18n: is there support for translations and multiple languages?
  3. Hot reload: are changes visible immediately or is there a compile/deploy cycle?
  4. Performance: how long does it take to render in the browser and server?
  5. Ramp-up time: how is the learning curve?
  6. Ramped-up productivity: once you've ramped-up, how fast can you build things?
  7. Server/client support: can the same template be rendered both client-side and server-side?
  8. Community: is there an active community using this project? Can you google issues?
  9. Library agnostic: are there dependencies on other JS libraries, such as jQuery or Mootools?
  10. Testable: how hard is it to write unit and integration tests?
  11. Debuggable: is it possible to step through the code while it's running to track down errors?
  12. Editor support: is there an editor with auto-complete, syntax highlighting, error checking, etc?
  13. Maturity: is this a relatively stable project or still experimenting and churning?
  14. Documentation: how is the documentation?
  15. Code documentation: do the templates encourage/require documentation/comments?

The Score

After running through the test, the teams gave the 18 candidate solutions the scores listed below. This evaluation was done in March and April of 2011.

The Four Finalists

After going through the evaluation process, we had a four way tie for first place between Google Closure Templates, mustache, handlebars, and dust.js. Since many different front-end engineers conducted these evaluations, we knew there would be some inconsistencies between the way people picked ratings, so we didn't read too much into the numbers themselves.

Instead, we took the scorecard as an indicator of which templating options deserved the most attention. From there, to pick the winner, we got detailed feedback on each of the finalists, as listed below.

Google Closure Templates

  • + Templates are compiled into JavaScript for client-side and Java for server-side.
  • + Good built-in functionality: loops, conditionals, partials, i18n.
  • + Documentation is enforced by the template.
  • - Very little usage outside of Google. No plans to push new versions or accept new contributions.
  • - Some functionality is missing, such as being able to loop over maps.
  • - Not DRY: adding new functionality requires implementing plugins in both Java and JavaScript.

Mustache

  • + Very popular choice with a large, active community.
  • + Server side support in many languages, including Java.
  • + Logic-less templates do a great job of forcing you to separate presentation from logic.
  • + Clean syntax leads to templates that are easy to build, read, and maintain.
  • - A little too logic-less: basic tasks (e.g. label alternate rows with different CSS classes) are difficult.
  • - View logic is often pushed back to the server or implemented as a "lambda" (callable function).
  • - For lambdas to work on client and server, you must write them in JavaScript.

Handlebars

  • + Logic-less templates do a great job of forcing you to separate presentation from logic.
  • + Clean syntax leads to templates that are easy to build, read, and maintain.
  • + Compiled rather than interpreted templates.
  • + Better support for paths than mustache (ie, reaching deep into a context object).
  • + Better support for global helpers than mustache.
  • - Requires server-side JavaScript to render on the server.

Dust.js

  • + Logic-less templates do a great job of forcing you to separate presentation from logic.
  • + Clean syntax leads to templates that are easy to build, read, and maintain.
  • + Compiled rather than interpreted templates.
  • + Better support for paths than mustache (ie, reaching deep into a context object).
  • + Better support for global helpers than mustache.
  • + Inline parameters.
  • + Blocks & inline partials.
  • + Overriding contexts.
  • + Support for asynchronous rendering and streaming.
  • + Composable templates.
  • - Requires server-side JavaScript to render on the server.
  • - Maintainer of github repo is not responsive.

The Winner: Dust.js

Based on our evaluation and how we prioritized the requirements, dust.js came out as the winner. It was the option that offered the most features and flexibility while keeping the view code DRY, clean, and fast.

Despite some claims to the contrary, we found that for any non-trivial view, none of the templating options worked well across client and server unless the server could also execute JavaScript. Therefore, we've been experimenting with Rhino (check out the sample code) and Node.js (check out the sample code) as server-side JavaScript options.

As we roll client-side templates out to more of the site, we have been making tweaks and additions to dust that we hope to contribute back to the open source community. Expect another blog post about that in the future.

Acknowledgements

Special thanks to Brent Vincent and Yevgeniy Brikman for leading the client-side templating efforts, Eugene O’Neil, Scott Blackburn, Matt Edwards, and Jeffery Chow for quick hacks to provide feedback on the profile rendering use case, and all the other front-end engineers who participated in the template evaluation process.

Topics