Client-side Termplating with Jade and Node.js
At my current job, we heavily use client side templating, specifically Jade template engine. We've been using Jade for couple of months now and are very happy with it. In this post, I will describe how client side templating works and how to set up development environment that allows you to work on templates and then view them in browser quickly.
We use Jade in client side mode, which means that templates are compiled to JavaScript on server (using Node.js) and populated with values on client. If this sounds weird at first, read on, it should get clearer by the end of the post :)
Whole workflow looks like this:
- Edit
.jade
template file - Compile template files to JavaScript
- Refresh page in browser to see changes
Key here is detecting that there was change to one of .jade
files and recompiling templates; you definitely don't want to do that by hand.
Compiling templates
Compiling templates in Jade is very simple:
Now you have func
which is JavaScript function that you call with values you want to render your template with and func
returns you HTML that you just need to put somewhere on page. Since func
is executed in client's web browser we need to save func
to a JavaScript file (let's call that file templates.js
) and serve it as any other static file. So, templates.js
will contain all of our Jade templates compiled to JavaScript.
Since templates are usually in .jade
files, we need to parse all files and compile them. For that purpose, I wrote this short Node.js script:
In order to run this script, you need to have Node.js and Jade installed. After you install Node.js, Jade is simple:
npm install jade
Now run the script:
node jade_compile.js templates/ output/
If you go to output
folder, you will see a file called templates.js
which contains all your templates. You do not have to know how compiled templates look, but if you are interested in how exactly Jade compiles templates to JavaScript you can examine templates.js
file. Inside, you'll find a bunch of JavaScript functions assigned to variables, one variable for each .jade
file found in templates
folder. Eg. if you had a file called login.jade
, then templates.js
would contain a function named login
which, when called, returns HTML for your login form.
This is probably not the best way to do this because you have to link templates.js
in your client side code, and since we know that JavaScript sucks at namespaces, if there is something else called login
there would be name clashes. I deal with this by putting _tpl
suffix on each of our .jade
files, so we can access templates in browser by issuing simple login_tpl()
. If your application is really large, probably the best solution would be to introduce namespaces to templates.js
file.
Detecting changes
Now that we have a way to compile all our templates, we need some way of detecting changes to .jade
files and run compilation automatically. I use Watchdog library that comes with simple watchmedo
command:
Basically, this command tells Watchdog to start monitoring *.jade
files in templates
folder, and if anything changes, run node jade_compile.js templates/ output/
command.
Performance
If you are worried about compiling all your templates every time you change something in any template, don't be. Node.js is very fast with this compilation, you probably can't Alt+Tab to browser faster than Node compiles your templates. If you have a lot of templates, try this way first and if it turns out too slow for you, then introduce some logic to template change detection process. First thing that comes to my mind is separating templates into smaller chunks (multiple folders) and treat each of them as described above.
Conclusion
This whole process can seem a bit complicated when you read it first, but in reality it's really integrating couple of tools the way you need them to work. It took me couple of hours to set it up and I haven't touched it for couple of months now, it just works.