Общо показвания

септември 05, 2011

Javascript client-side templates

How to use jade templates on the client side with requireJS.

I am working on a rather big project targeting webkit embedded environment and I was looking for client side templates that can be loaded at runtime (i.e. dynamically) and do not require the loading of iframe (because of some internal requirements posed by an C++/JS extension in the environment ).

I was using jade on node server for some time and I like the clean syntax, I never ever liked HTML syntax.

To use the jade format on the client side you need the jade code:

$ git clone git://github.com/visionmedia/jade.git
Compile the minified or the regular version as needed:

$ cd jade && make jade[.min].js
The compiled version however leaks the 'require' function in the global name space and as we are using requireJS for the project (I recommend it - a lot!) we had to enclose the resulting jade code in a define:
$ echo -n "define(function(){" > requirejs-jade.js && cat jade.min.js >> requirejs-jade.js && echo -n "return require('jade.js');});" >> requirejs-jade.js && mv require-jade.js jade.js
 After that we were able to allow each module to define its own template(s) at load time and use lazy load of all modules as usual:

//module that can be loaded whenever the envoronment needs it
define(['jade.js' , '!text/templates/atemplate.jade'], function(jade, jadetpl) {
    var tpl = jade.compile(jadetpl);
    var data = {/*some data*/};
    $('#container').innerHTML = tpl(data);
    return {/*module's public interface*/};
The pre-compiled to JS functions modules can be loaded from the server also! This was tested in Firefox and webkit as those are the environments targeted. I will update once I test it in IE also.

I have tested it in IE, of course it fails miserably, however the pre-compiled templates work (of course you need to fix the runtime.js as it contains schims for Arrya.isArray and Object.keys which seem to not have been tested (I have reported this in github, the author will fix it soon probably)). If you are looking for working with client side templates in IE environment you will probably need to pre-compile your templates on the server (done only once) and it will turn them into javascript functions. If you want to use those with requireJS you will need to decorate them a little bit, here is my decoration (this is done 'live' on the server as we are still in development phase and we change the templates a lot, so we provide a compiled template on request instead of pre-compiling them all, the pre-compilation should be done in the build however, before deploying):

var a = jade.compile(data, {
      compileDebug: false,
      client: true
a = 'define(["support/runtime"],function(jade){' + a.toString() + 'return { render: anonymous }; });';
And then on the client:

require(['tpl/tplname'], funcrion(tpl) { var html = tpl.render(data)});

As seen, the returned fragment will be requireJS compliant js script, the dependency (runtime.js) also was altered so it does not leak in global namespace (i.e. I made it also requireJS compliant).

In brief: it is possible to use client side templates (regular jade or pre-compiled, depending on how much you are willing to trace the issues in IE). On the performance side I have not yet completed the tests, regardless of the tests however the flexibility templates provide will compensate the slow down, especially with pre-compiled templates (those are very simple scripts and look a lot like the usual string concatenation method).

Няма коментари: