Stop sending template engines to the browser. How to make 6-10x faster templates
andyet.net
andyet.net
[1] http://akdubya.github.com/dustjs/
[2] http://engineering.linkedin.com/frontend/client-side-templat...
You can do this with Handlebars. I use a Grunt task to pre-compile all templates and then I just bundle them with the much smaller (it adds about 1kb or so) "vm" version of Handlebars.
Locally, I use the full version of Handlebars and regular non-compiled templates.
Handlebars.partials = Handlebars.templates
:) Handlebars.registerPartial("Foo", Handlebars.templates.Foo);
Your approach is kinda amazing. Makes me wonder why not all templates are automatically available as partial by default. Are there cases where you wouldn't want that? var getHtml = Handlebars.compile("<div>yad yada...</div>");
And then following the rule of least surprise, if templates aren't partials during normal usage, then they shouldn't be with precompilation.At least that's my guess. I didn't figure out my trick until digging through the source to figure out what was different. (Not much - just how/where they're stored & referenced.)
The whole approach strikes me as odd, unless I'm missing something.
My team uses Handlebars templates with Ember.js. We build templates with placeholders for bound values or other view templates. When rendered on the client side, a change to a data model causes an automatic change in any templates that are bound to that data. In jQuery there's a potential for forgetting to write code to update a value or part of the page. With this templating system, it's all bound and auto-updated.
Another reason that we use templates is that we put all the template files up on a CDN. The only thing our server serves up is an empty DOM (just a body and a div), and the templates are all built into the DOM on the client side.
Lastly, managing a bunch of small tmpl files with the HTML we want is a lot easier than trying to embed HTML into JavaScript strings to use with jQuery. We just write up some HTML and an Ember view that renders that template in the right place on the page. Organizationally it's very simple and easy to maintain.
It also leads to jQuery spaghetti code. So many people use jquery like a shotgun, to solve every JS problem, when better - and more targeted - solutions can be tailored out of small modular libraries.
Then you "bind" that to some kind of object. Whenever the object changes, the framework then re-renders the template. So the effect is that when your model changes all of your UI components on the page just magically refreshes themselves.
Probably not the best explanation, but hopefully makes sense!
It's used like this:
el ( tagName, properties, children )
Working with data structures is easy, children is just an array which can be the results of something like data.map() turning the data into elements.An added benefit is that it's very easy to attach events or other javascript properties to any object in the hierarchy.
TLDR: It depends, but DOM manipulation tends to be faster in newer browsers.
<div id='thingToReplaceWithData1234"></div>
and then adding a child text node or such to that element. Whether you do that via InnerHTML or CreateTextNode doesn't matter, either seems faster and easier to me than doing a string substitution.
But I don't know, I never really got the appeal of the framework of the week. If it helps write decent web sites, then I guess that's good, but I've noticed that simple sites now are ridiculously slow and I'm guessing this is the reason.
The reason people use templating languages client-side are exactly the same as they use them server-side, it's much easier to maintain a larger app.
Most template languages are extremely lightweight and blazingly fast, slow websites are 99% of the time due to sending too much content or slow server-side processing.
I can think of a couple of ways to do that but it hasn't taken off largely yet:
https://www.facebook.com/notes/facebook-engineering/xhp-a-ne...
Part of the issue is that the default bin/handlebars script doesn't really support walking a tree and outputting a directory structure with all of the precompiled templates, but I've got my own hacked version of it which does...
https://gist.github.com/3719225
handlebars ./handlebars --min --outputDir ./js/tmpl
I also have a build script setup in Eclipse so that when I save the file, it automatically builds things... (similar to this)...http://stackoverflow.com/questions/6645640/integrating-coffe...
I use requirejs with a paths configuration like this:
handlebars: 'handlebars.runtime-1.0.0.beta.6'
This allows me to just write this in my CoffeeScript for each page on my site... require('handlebars')
require('tmpl/org/requests')
...
requests.html(Handlebars.templates.org_requests(requests: requests)
All of this works amazingly well and has really allowed me to segment my code and templates up into little sections for reusability. Also, no need for ever loading the compiler part of handlebars in the client even during development.I guess this is why frameworks like Rails compile your assets for you - it's a "silly not to do it" task, but not everyone knows about it.
"It is also possible to precompile your templates. This will result in a smaller required runtime library and significant savings from not having to compile the template in the browser. This can be especially important when working with mobile devices."
But nobody reads documentation... ;-)
When you have 3- or 4-level nested templates with 50+ fields to fill in, it's much easier to write (and especially to maintain) the snippets of HTML with {{name}}-type template tags, rather than writing the code to query the DOM and replace elements as needed. Especially if you have a designer who's comfortable manipulating HTML elements but allergic to JavaScript.
If a renderer comes across a script tag it doesn't know how to parse (e.g., a script of type `text/template`), it doesn't do anything with it, however it remains the responsibility of the markup renderer and, therefore, you're not relying on something else (CSS or JavaScript) to hide it.
<script type="whatever"> is mostly used because it's completely ignored. It's safely hidden, difficult to be accidentally messed with, and doesn't take parsing/rendering time from the browser.
Regarding the `hidden` attribute, there is no support for it in IE (at least up to and including 9).
DOM manipulation has traditionally been slower than innerHTML, which is another reason people might have shied away from this approach. I believe the performance gap is no longer clearcut though, so the argument may not hold for recent browsers at least.
You should probably never be parsing templates on the client.
As someone just learning Backbone.js this stuff fascinates me :)
2) These days more work just happens on the front end. With some web apps the back end is a pure data store and all the GUI is rendered on the front end. Doing a round trip for each front-end change would make the UI to unresponsive to be useful.
That, yes. I noticed that my CPU load was noticeably high browsing some sites. Nothin special, just news sites. I found that quite annoying so I activated NoScript, suddenly the load was gone. The problem is, that NoScript seems to "deactivate" half of the web for me these days, precisely because of client-side templating.
There've been some valid reasons stated here though. However, the site I'm working on uses server-side templating, that's why I was asking in the first place.
A lot of stuff is being pushed to the client now to reduce the amount of crosstalk between client and server, so things feel snappier for the user, with the goal to be to talk to the server when absolutely required (i.e. to save data or application state, to request new data or check the data the client has is up-to-date, or when some of your business logic needs to make a decision the client-side can't be trusted with).
If you are making display decisions client-side then your template engine probably needs to be client-side.
https://bitbucket.org/djc/jasinja
It reuses the Jinja front-end, it really only replaces Jinja's code generator and supports a pretty large subset of Jinja. I think this is particularly great because it allows you to switch from server-side template rendering to client-side rendering of templates piecemeal, or use both with the same templating language.
var Jasinja = {
"filters": {
"attr": function(obj, name) { return obj[name]; }
},
"tests": {
"lower": function(val) { return val.toLowerCase() == val; }
},
"templates": {
"test": {
"macros": {},
"blocks": {},
"render": function(ctx, tmpl) {
return "a";
}
}
}
};
So you can easily add some filters by setting Jasinja.filters['myfilter'] to a function.Something like this: https://github.com/comolongo/Yz-Javascript-Django-Template-C...
It might be possible to have code where you just transparently wrote normal server-side views and the framework intelligently decided whether to render on the server or client and handled all the plumbing for you.
There's basically 4 strategies:
1. Give the client a full html page
2. Give the client pre-rendered html snippets
3. Give the client javascript that can render html and replace values without having to do much computation
4. Make the client do the template rendering probably using a library such as mustache.
So...
1. Should be the default and the fallback for dumb devices such as spiders and old browsers
2. Is ideal if the page doesn't change much - typical content heavy sites. You have to have proper urls and history management though.
3. is optimal for "it's an app not a website"
4. is only OK if you know your clients have plenty of CPU to spare. So not mobile basically...
handlebars: {
compile: {
options: {
namespace: "JST"
},
files: {
"dist/debug/templates.js": ["templates/**/*.hbs"]
}
}
},
Then you can concat templates.js with the rest of your JS and your template functions are ready to go!If it was happening at run-time, I'd probably rather just have the client do the compiling instead of the server. Since the client isn't going to notice a few extra milliseconds, but on the server that can add up under high load.
http://backstage.soundcloud.com/2012/06/building-the-next-so...
(BTW, I just mean this as informative. I wish more people were aware of this idea, and I wish more mainstream languages would make this easier.)
If I have a single page web app, I don't want the overhead of returning markup. I just want JSON. And when I get raw data back instead of a string of HTML, I can be a lot smarter about responding to user input (e.g. optimistic updates).
Also, sending JSON back and forth is kinda nice because it's fairly compact, easy to handle on both sides, and additionally this particular API may be used for other purposes, too.
Rendering speed isn't the reason server-side templates feel "slow" though: if you do server-side rendering then every change of state on the client needs to round-trip to the server in order to fetch a new HTML representation. Client-side rendering lets you "cheat": just render the new state and synchronize with the server after the fact.