Template engine – Why it’s better to use two of them at once?

Template engine

In the following post I’ll try to show and explain how and why I am using two template engines in every application I’m working on. Also, why and how I am choosing my template engine(s) I’m working with.

Intro (about me)

Developing in: .NET / Python / Java / Go / PHP and more,

  • New exciting and better tools are important to me!
  • Performance (server & client) are very important to me!
  • The ability to arrange and split the code smartly exact as I want is very important to me!
  • The ability to comment as I like inside the code and the client not to receive it is very important to me! (especially in web HTML/JS)

Who using Template engine

Probably every web developer is using a template engine. You can find it as integral part of most decent modern web development frameworks and environments. Many exist standalone and not as part of any framework. although, Templates Engines are not sole exist for Web development and are used in large variety of tasks. This post is dedicated to web development Template Engines which are called specifically – “Web Template System”

If you’re a web developer and you don’t know or use any Template Engine: You better run some self-tests(!). If you don’t know what is template engine and how to use it, you better read before you continue…

Note about PHP. as I call PHP a bad language but a great Template engine by itself, so in many cases Template engine doesn’t needed or not used (although there are many PHP templates engines).


So, Why one template engine? Why not 2?

All configurations of template engine I saw are using one template engine per application. The scenario is simple; The web developer creates a template for an HTML page.. process it on the server and send the results to the browser. for example:


In the above example, the server will fill the $title variable as needed and result with the following to the client:

   <title>Using My Template Engine</title>


Now.. for my suggestion.

I’ve changed the way I am using template engine in my development. I am using two separate template engines in the app. One for creating minified html files with embedded JS and CSS, the other for filling the variables and send to the client.

I call the first TE(Template Engine) – The ‘First layer’, and second ‘Second layer’.


Example of 2-Layers-TE

Maybe It’s the best to show an example of how I am using my Templates engines together.

In this example I am rendering at first HTML using Tenjin (Python) and the second template engine as the web server is the basic Golang Template engine.

First Template Engine

<!-- all comments will be removed at the minify process -->
   <style><?py include('index.css') ?></style>
   <script type="text/javascript"><?py include('index.js') ?></script>
   <title>{{ .Title }}</title>

In the above example with Tenjin, you can see it includes two files: index.css and index.js which I I’ll show below. Also note the {{ .Title }} annotation which is NOT tenjin syntax but it’s golang template engine syntax, which means the first template engine (Tenjin) will just output this into the final html result.

The Styles are saved in another file (index.css):

// All comments will be removed at the minify process
body { background-color: blue }

Actually, I am using SCSS (SASS) for my CSS development, and then I compile and minify them (in the same script as part of the whole website compile) into index.min.css file. then, the above Tenjin imports index.min.css and not index.css. Also, I’m adding one more global.css which is embedded into all htmls.

And the JS are saved in another file (index.js):

$(function () {
 // also, those comments will be removed on minify

As with the CSS, sometimes I use CoffeeScript or IcedCoffeeScript and then compile it into JS.
Also, as part of the compile process, I am minifying the JS to index.min.js and Tenjin imports the minified file and not the source. If I use JS (and not CS or ICS) I minifyjs it before too, and in the process doing a syntax check.

Then, Using script I made – I minify all the templates (with inline CSS and JS) onto:

<html><head><style>body{background-color:blue}</style><script type="text/javascript">$(function(){});</script><title>{{ .Title }}</title></head><body></body></html>

You can see that the {{ .Title }}, which is Golang template engine syntax is still here. The first template engine (which in our case is Tenjin) isn’t processing the variables and just minify them with everything else.

Now, its ready to use from the Golang environment Template Engine. comment-less, minified and as one document, even if it’s built from 10 CSS files, 10 JS files and hierarchical templating.

In this way the actual logic designing of the hierarchy of the templates are done in the first layer and the second layer is only responsible to fill in the variables and pass to the client.

How I choose the templates engines?

The equation I use is simple:

FOR THE FIRST LAYER I use for the strongest template engine I can find. I like features like inheritance, raw, import, widgets …… ! I need everything! Performance isn’t needed at all at the first layer. It’s compiled after work has done in the code and then that’s it!. I want to be able to arrange my website htmls into preety smart structure. To split the JS files into many logic files… same with CSS. After it will be rendered for the second layer it will be fully minified as one document. then the performance matters…

FOR THE SECOND LAYER I use the fastest template engine I can find. Caching of templates is a must feature! Here the performance matters!. The template engine could be Logic-Free or not, It’s design decision, but no need here for hierarchy or any other expert feature in the TE as it using the full minified htmls. only to read the html from file into memory and then fill it now and then with data and pass to client.

REMEMBER You need to choose two TE with different syntax(!). You can’t use two of them that has the same snytax (like {{ var }}). Tenjing is using <% %> and Golang is using {{ }}.

If you’ll later use client side TE you better take that into account. AngularJS is using {{}}. Angular Syntax must be changed or another TE must be chosen for the second layer.


So, Why it’s good for?

So, Why I am doing this complex structure? Those are the advantages of this method:

  • Performance – Golang caches into memory the minified html with css, js embedded. it’s better for server side and for client side performance!!. It’s PRO! and minification doesn’t need to be done in real time!
  • You can create a complex inheritance for your files in the first layer WHILE you preserve performance in the second layer. You get to write and split code (html, css and js) in many files as you like. you know it will be all be merged and minified later….
  • You can put comments wherever you want freely!! (in the html as well as in the css/js) and they will be removed later by the minify process.
  • You can use Placeholders as usual in the webserver template engine (second layer), as well in the first layer.  application name, for example will be suited for the first layer as It doesn’t supposed to be changed but user name can be filled as usually in the second layer.
  • JS files are verified in the process!!. you will know about bad syntax before you’ll even open the browser!
  • If you use SASS you’ll find it’s so sweet… at last! you can manage your CSS as you’ve always dreamed of!


I made an example @ Github (https://github.com/ET-CS/2TE). I used Cheetah(Python) as the first layer, as it have lot more features then Tenjin, and I’ve used Golang as the webserver (second layer). although Golang is not the fastest TE I know, it’s fast enough and I really like Golang as a web server.

I made another example @ https://github.com/ET-CS/2TE-Bootstrap which is essentially the same idea as 2TE, but it is ready packed with Bootstrap HTML on either Jinja2 or Cheetah as the First layer. Great boilerplate for amazing fast web application!!


Always think performance…… and always MInified is better!!!

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.