Isomorphic Javascript using Mustache Templates

Mustache is my goto html templating engine. I find it incredibly simple and expressive and I guess authors of Angular and Ember also felt the same way – both frameworks use similar syntax.

But there is a price. A big problem with both these frameworks is the requirement for javascript to be enabled, and the potential for the flash of content as the templates get compiled and populated from the model. Pages can also take a long time to load. Meh.

The increasing popularity of isometric frameworks such as React got me thinking – what if we could get all the productivity and simplicity of Mustache templates, without the associated problems? In other words, is it possible to render the template on the server (the isomorphic part), and use progressive enhancement to re-render any  content using mustache on-the-fly?

The following examples (Example 1 and Example 2) show the problem. Example 3 demonstrates how an isomorphic approach could work. Click on the tabs above each example to show or hide the html markup, script and screen output.

Example 1 – simple mustache template

JS BinThe purpose of this example is to render a mustache template that has been defined directly in the page markup. A template is turned into content using the following phases: parsing -> tokens -> rendering. To achieve this, the javascript takes the html inside the test-flight element, compiles the template into a set of tokens, renders the tokens with our sample model, and replaces the template markup with the rendered version. This is a pretty common approach – but why is it so bad? First, you may experience a horrible flash of un-rendered content as the template gets replaced by the rendered content. You can work round this, but you sacrifice performance – it can be significantly longer before your page is viewable. Other potential problems I can think of are possible search engine indexing issues. I think this blog post Don’t depend on your javascript to render your page sums up the argument nicely. So how can we do this better? First let’s set up this example so it makes sense for us to want to render the template on the server as well as the client.

Example 2 – client side render and re-render

JS Bin

Press the update button to re-render the view of our updated model data.

All we are doing here is rendering the template with two different models e.g. parsing -> tokens -> render -> render. Note – this example is still bad for the same reasons as before, but now we have a reason to make this example isomorphic, as opposed to just rendering the content on the server.

To make this isomorphic, we need to render the first pass on the server and, since we have now replaced our template with rendered content, transfer the template to the client, so that our client script can carry on using the template as normal. Lucky then that Mustache js was written in a way that its really easy to convert the tokens created from the mustache template to JSON, which can then be sent down to the browser.

Example 3 – initial server render with client update

Isomorphic Javascript with Mustache | Example 3

I didn’t actually need to write any server code, but instead added the markup that would have been rendered by any standard Mustache library on the server, and then included the template tokens as a JSON variable in the javascript – as if it had been loaded via ajax or some other mechanism. It may as well be a plain html page that we are starting with in the browser because it kind of is.

This feels a lot better to me. We can add mustache templates to our markup, knowing that these will get processed by the server and delivered to the client if we need to update the markup later. In the browser, the libraries and application code for doing this can now be loaded after initial page view, off of the critical path. In this basic example, this code is required only by the time the user is presses the update button.

Pro’s

For me the biggest win here is that you can use mustache templates as your view logic without worrying about performance on the client or any nasty flashes of text. You progressively enhance the page delivered from the server as per best practices. There is no need for <script type=”x-mustache”> hacks in your markup either, because the template is rendered by the server using e.g. Node.js. With a bit of work, this technique could become a pretty seamless way of moving data from your model to your view, no matter if that code is running on the server or browser.

Con’s

If you bind event handlers to the generated markup those are going to get lost every time you replace the innerHtml with your new markup – unless you use event delegation on the container element (which is no bad thing).

Template parsing is expensive for the server and tokens may end up being quite large, so possibly you would need to write the code so that the template tokens are cached until they change. You could also follow the Hogan model and precompile your templates as a build step, and distribute them with your application code, but theres less need for that now that startup performance is no longer an issue.

In my next post, I’ll also explore a dom reconciliation algorithm to more intelligently merge any changes rendered by the template into the dom. This will remove the worry about the impact of replacing large sections of the dom using the innerHtml technique and make this part of the process less of a hack. This is also the approach React takes and it was a whole lot of fun to figure out.

Get the code on GitHub

Isomorphic Javascript using Mustache Templates