This is my first foray into client-side templating and I want to make sure I'm understanding it and using it correctly. After reading this LinkedIn engineering blog, I decided to go with dust.js rather than mustache or handlebars. Note that this stackoverflow post answered many of my questions, but I still have a few things I want to clarify.
In the environment I work in I have no access to anything on the server side, so everything I create has to be able to run entirely in the client's browser. For this example, I'll try to recreate this code sample from the LinkedIn Dust Tutorial.
I include dust-full.js rather than dust-core.js because I'm going to compile the template on the fly:
<script src="js/dust-full.js"></script>
Here is the HTML:
<script id="entry-template">
{title}
<ul>
{#names}
<li>{name}</li>{~n}
{/names}
</ul>
</script>
<div id="output"></div>
And the JavaScript (using jQuery):
$(document).ready(function () {
var data = {
"title": "Famous People",
"names" : [{ "name": "Larry" },{ "name": "Curly" },{ "name": "Moe" }]
}
var source = $("#entry-template").html();
var compiled = dust.compile(source, "intro");
dust.loadSource(compiled);
dust.render("intro", data, function(err, out) {
$("#output").html(out);
});
});
This seems to work fine, as you can see in this jsfiddle.
A couple questions:
Why should the template be contained within script tags? Why not just include it in a div with id="entry-template" and then replace the html inside that during the dust.render(), like in this modified fiddle?
What does "dust.loadSource(compiled);" do? In the docs it says "If you include the 'compiled' string as part of a script block of JS that you load, then the 'intro' template will be defined and registered. If you want to do it immediately then" call it, however I do not understand what that means. I have noticed that if I remove that line then it doesn't work, however, so I'd like to understand it.
After I'm satisfied with my template and finalize it, how should I compile it so that I import the lighter dust-core.js rather than have it be compiled by the browser on every page load? Is there a significant advantage to doing this or should I leave as is with dust-full.js?
More generally, does this look like an appropriate / useful way to implement dust (or any templating framework for that matter) or am I just way off somewhere?
Thanks in advance.
If you put it in a div
, the markup will render as soon as the page loads, and with contain the dust {placeholder}
syntax. Then, once the client-side rendering happens, it'll suddenly be replaced with the fully rendered content. In a simple example, this can happen so fast you don't notice it. However, depending on how long it takes to download the templates, the dust JS libraries, fetch the JSON (if it's not already embedded in the page), the JS performance of the browser, and other things happening on the page, this switch may be very noticeable to a user, which is not a good experience.
When you compile a dust template, the output is String that contains a JavaScript function. It will look something like:
(function() { dust.register("intro", body0); function body0(chk, ctx) { /* [...] */ } })();
When you pass this string to dust.loadSource, all it does is eval
it, executing this self-calling function. The result is that the dust.register
call executes, which associates the body0
function with the name intro
in dust.cache
. After that, every time you call dust.render("intro"...)
, dust looks up the intro
template in dust.cache
and executes the function associated with it.
Store the output of dust.compile
in a .js
file, such as intro.js
for the example above. You can then include dust-core.js
and intro.js
on the page just like any other JavaScript files (e.g. in script tags
or via loaders).
Usually, you store each dust template in a separate file, such as intro.tl
and use some sort of build system (e.g. http://gruntjs.com/) to automatically compile it into a .js
file every time it changes. You then concatenate all the generated .js
files into a single file (grunt can do this too) and load that on the page in a script
tag.