Basic Example of Client Side Templating with Dust.js
Asked Answered
T

2

19

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:

  1. 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?

  2. 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.

  3. 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?

  4. 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.

Tricycle answered 25/1, 2014 at 21:4 Comment(0)
T
11
  1. 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.

  2. 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.

  3. 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).

  4. 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.

Twenty answered 28/1, 2014 at 5:44 Comment(2)
Thanks Yevgeniy! So about question #1, does that mean that dynamic pages set up with dust generally have little to no actual HTML in them? Pretty much just import the compiled template, render it with whatever data, then insert that into an empty div? Thanks for the grunt link!Tricycle
@DougieBear Yes, webpages that use client-side rendering have relatively little markup. It's typically just enough markup to lay out the basic structure of the page and then script tags and embedded JSON to fill in all the pieces.Twenty
S
1
  1. You shouldn't have to contain the template in script tags, your second way is better.

  2. loadSource will run the compiled output of your template, which includes registering it so that other templates and dust.render can reference the compiled output chain through its name ("intro" in this case).

  3. This involves pre compiling your templates before you even open up the browser. So you might have a folder that has all your templates as .tl files. In some build step, you would compile all these templates (using dust.compile) and save the output as .js files. Then the browser would actually load those .js files. This also gets rid of the need for dust.loadSource. The advantage here is not having to include the compiler and the parser, which add up to ~3000 lines of code. The dust library size goes from 4000 lines of code to just 800 lines of code. EDIT: Also, as you mentioned, you're not compiling templates on the fly in the browser, so that will also be a big performance gain.

  4. I'd say other than missing the build step I mentioned above, you're on the right path.

Sin answered 27/1, 2014 at 8:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.