GoalsThe goals for the project were pretty ambitious.
- Trivial to convert from Jinja to Bujagali
- Support template inheritance
- Support importing shared code
- Support filters (essentially just functions accessible from the template)
- Make heavy use of client’s cache
- Reduce bandwidth usage to being as close as possible to the size of the actual data required to render
- Perform really, really fast on good browsers
- Not have terrible performance in IE
- Optionally render server-side to support googlebot and other limited JS environments
If you want to learn how all the insides work, keep reading.
ArchitectureThe architecture is pretty simple on the surface. It comes down to heavy caching, robust versioning, a laissez-faire syntax, and flexibility in runtime environment.
A quick note about measuring performance: it’s hard. Bujagali is optimized to perform better over time, to get you your data faster by utilizing smaller payloads, and to actually be fast once we were shoving data into strings. To top it off, it performs differently depending on your client. It’s hard to do an apples-to-apples comparison of overall template performance in a case like this, but suffice it to say that we measured performance extensively at rdio and Bujagali is way, way faster in most cases than the previous Jinja2-based system. I hope to write more about performance in the future.
As long as we carefully keep track of versions, we can be sure that the function loaded by the above script is the one that we want and that if the template does not change, it will never require another trip to the server to retrieve. In practice, this is a huge win as the full markup of your site really only has to be transferred once.
The next overriding principle was strict versioning. This was pretty much necessary as a result of the heavy caching. Every time data is passed into Bujagali to be rendered, it must specify what version of the template it expects to be rendered against. By providing this information every time, we can be sure that the templates always work right in pretty much every possible proxy and caching set-up. A cool side effect of this is hot-swappable templates. If you modify a template server side and an ajax request comes in for data that’s supposed to render against that freshly modified template, Bujagali will reload the template and render it seamlessly, no refresh required.
This restriction on environment does have some practical benefits that keep the templates “clean”, despite the arbitrary JS that is permitted. Without access to the DOM or the rest of the running program, side effects from the templates themselves are limited. This restriction is not actually enforced by Bujagali itself, however, instead you’ll just get burned if you don’t stick to the restriction and then try to use your template in a different context.
Try it outI’ll write more about actually using Bujagali in the future. However, the code is available now on github. The documentation is a bit thrown together right now, but it’s hopefully enough to get you started. There’s some infrastructure required since, unlike a normal templating system, this system spans the boundary between client and server. Luckily the code provided should make it fairly easy to get going if you already know what you’re doing.
It should be stated that this isn’t exactly a templating system for the faint of heart. Best of luck to all who venture on to github.