Mustache 2.0 and the Future of Mustache.js
writing.jan.io
writing.jan.io
Your dumb parser may be quick the first time, but when you have to render a template 100 or 1,000 or 1,000,000 times the cracks will start to show. One main benefit of parsing and compiling templates is that you can cache the result of that stage on the server.
If you want to be really smart about it, the client shouldn’t even be downloading a .mustache template — it should download a .js file containing a pre-generated function which can be called with the context, returning the rendered template. Parsing the template on the client side makes about as much sense as parsing JSON or XML with a hand-written pure-JavaScript parser.
"eval"?
On being "really smart": These are design goals different from mustache[.js] and can be freely implemented in any other templating library if people want it.
This would render browser-side mustache as moot. Now the server side implementations must render javascript functions. handlebars.rb, handlebars.py, handlebars.php, handlebars.cs anybody?
This lets me use the same views on the server and the client, with the same $templates.render("item", context); where "item.html.haml" is the name of the source file. I pre-compile the source of all the .haml files to functions and add them to the $templates object (boo, globals, yadda yadda yadda) and then write this out to a file for serving to the browser (./public/templates.js by default.)
Then, when I make a json call or whatever and need to re-render a partial, i just call the same template rendering.
Note that this works for Node.js but you could easily make it work with ruby through redcar or use a similar technique for precompiling your mustache templates for the browser while still using your language-native implementation on the server.
Edit: forgot the link https://github.com/aaronblohowiak/shared-views
Because the server generates the javascript template methods. Thus the browser does not need to parse the mustache templates. It only needs to call the compiled functions. This means the browser would not need to have an implementation of mustache running on it, since the template building is contained within the compiled javascript functions.
In the browser you will not render thousand times a template. And the tens milliseconds you will save if you pre-compile the template is irrelevant compared to the hundreds milliseconds of network latency and page & js load time.
I wrote http://beebole.com/pure another template engine. With the version-2 we dropped the pre-compilation. The small performance gain wasn't worth the complexity.
Ten milliseconds here, ten milliseconds there, pretty soon you're talking about real time. Especially if I can manage to browser-cache away the page & js load time you mention.
It solves ALL of these problems. It has {.or}, the dot notation, and searches up the stack of contexts for variables.
I haven't been working on it for awhile, mostly because it does the job, but the codebase is small and easily hackable.
EDIT: It also compiles the templates and lets you change the delimiters! And has support for several other languages.
As an alternative, it looks good, so thanks for bringing it up.
{{^something}} {{/something}}
The draw of mustache is that it does things implicitly. I don't have to worry about .section, .repeated, .or, |html, for example. Mustache does it for me.
That being said, one thing that mustache does need to address is the difference between conditionals and repeated operations as needed (handled by .section and .repeated in JSON Template).
AFAIK, the songs template would require a boolean to be passed in of the existence of songs in mustache, since mustache would implicitly assume that {{#songs}} was a loop and create multiple tables.
http://json-template.googlecode.com/svn/trunk/doc/Introducin...
You seem to be on the fence about if you want an explicit "repeated" or not. I haven't thought about it too much but it seems cleaner to be explicit. I don't want to confuse an object {} and a singleton array [{}].
I don't know about the python version, but I had a look at the Javascript code for json-template. At first look it seems pretty "hacky". The main obvious flaws I saw were:
- it's polluting the global namespace a lot. Introducing a lot of functions and variables. - it's roughly 800 lines, while mustache.js is just over 300. I realize json template has more features. - A lot of the javascript could do with some optimization. Especially some of the loops.
But maybe that's something you simply want help with?
If you have some speedups I'm open to it, although I think it is pretty fast as it doesn't parse the template on every expansion.
Don't care on dotted access.
Context addressing is fine if we can agree on a method and keep the spec simple. Perhaps using Git's SHA addressing with things like HEAD, HEAD^, HEAD^^ or similar.
Yes to booting dynamically changing delimiters.
Yes to stealing helpers.
For cross-language compatibility, we really should have a collection of test inputs and outputs.
We should adopt a directive thing like you have for the 'this' notation with {{.}} or whatever for lists. The original is a bit funny looking but I think this sort of thing would fix the delimiter issue.
Another pattern that I run into that's a bit weird is when I need to add markup around a list when its not empty. I end up having a context that returns a context with a rows object when there is data, or None when there are no rows. So it looks like this in mustache:
{{#genes}} open table {{#rows}} row stuff {{/rows}} end table {{/genes}}
I keep having the feeling there's a better way to make that work.
If I get another project finished up shortly I'll write these up in a branch of pystache.
JSON templates has an interesting solution.
http://json-template.googlecode.com/svn/trunk/doc/Introducin...
{.section genes} open table {.repeated section @} row stuff {.end} end table {.end}
BTW, jQuery-tmpl is supposed to become "jQuery/DOM" free in a few, which allow to use it on the server-side as well (assuming Javascript).
Most programmers are familiar with the common notations for nested structures (e.g.: a dot, or a slash). Mustache's solution requires a programmer to explicitly reference the parent context: https://github.com/defunkt/mustache/issues/issue/6#issue/6/c...
https://gist.github.com/3c91441597ac650146b9
Maybe this was to keep Mustache "pure", and avoid introducing a dot- or slash- syntax. "Turtles all the way down"?
I agree the syntax is clunky. But it does have some internal logic.
I'd argue that the bigger problem is: most people don't know the feature exists.
Most web pages would not benefit from this but many web apps can and do.
And for recurrent visitors. The logic(HTML, CSS, JS) is in the browser's cache. Then only data travel the network from the 2nd visit, freeing even more your server.
I hope you don't get bogged down waiting for consensus from the "mustache community". Better to implement and put a stake in the ground, I think.
So, I'd be totally willing to help on that part :)
I'll have to keep an eye on the 2.0 project.
There are some features that do not seem to be consistent across implementations. For example, partial templates are handled differently in mustache.rb and mustache.js.
It seems like there are attempts to "embrace and extend" the mustache language (handlebars and mustache.js), which is fine, as long as the spec is adhered to and the good features get folded into the spec.
The difference between .rb and .js stems from JS lacking File.read(). But a 2.0 spec could work around that.
{ "items": ["foo", "bar"] }
# From mustache.rb
{{#items}} {{{to_s}}} {{/items}}