Alternative Dancer Templating Engines

Dancer uses a simple model of interfacing with templating engines (based on Dancer::Template::Abstract) and makes it very easy to add support for new engines. Thanks to this, if you're not happy with the default simple engine or with Template Toolkit, there is now a dozen different alternatives to choose from. Let's take a look at some of them.

Dancer::Template::Tiny

Template::Tiny is a lightweight engine which reimplements a subset of Template Toolkit features. As the name implies, it aims to accomplish this with as little code as possible. If you're using just the basic functionality of Template Toolkit, you should be able to switch to Template::Tiny without any modifications to template files (and you can easily go back at any moment).

Dancer::Template::Tiny is going to replace Dancer::Template::Simple as the default templating engine in Dancer2.

Example template:

<html>
 
<head>
   
<title>Tiny Example</title>
   
<link rel="stylesheet" href="[% request.uri_base %]/css/style.css" />
 
</head>
 
<body>
   
<h1>Hello, World! This is Dancer [% dancer_version %]!</h1>
   
<p>
      [% IF morning %]
        Good morning!
      [% ELSE %]
        Good afternoon!
      [% END %]
   
</p>
 
</body>
</html>

Route handler:

use DateTime;
   
get '/hello' => sub {
   
template 'hello', { morning => (localtime)[2] < 12, now => DateTime->now };
};

Dancer::Template::Tenjin

Tenjin is a very fast templating engine with implementations for many languages -- including, of course, Perl. Its great performance comes from the fact that it uses the underlying language's constructs to process templates, instead of defining its own templating language and having to parse it. Support for this engine in Dancer is provided by Dancer::Template::Tenjin.

Example template:

<html>
 
<head>
   
<title>Tenjin Example</title>
   
<link rel="stylesheet" href="[== $request->uri_base =]/css/style.css" />
 
</head>
 
<body>
   
<h1>Hello, World! This is Dancer [= $dancer_version =]!</h1>
   
<p>
     
<?pl if ((localtime)[2] < 12) { ?>
        Good morning!
     
<?pl } else { ?>
        Good afternoon!
     
<?pl } ?>
   
</p>
   
<p>
      Current time is: [== DateTime->now->hms =]
   
</p>
 
</body>
</html>

Route handler:

use DateTime;
   
get '/hello' => sub {
   
template 'hello';
};

Dancer::Template::Haml

Haml, which stands for "HTML Abstraction Markup Language", brings a fresh, different approach to templating. It aims at making templates short, clean, and as easy to read as well-formatted source code. Dancer::Template::Haml is a wrapper around Text::Haml and lets you use Haml templates in Dancer applications.

Example template:

%html
 
%head
   
%title Haml Example
   
%link(rel="stylesheet" href="#{$request->uri_base}/css/style.css")
 
%body
   
%h1 Hello, World! This is Dancer #{$dancer_version}!
   
%p
     
- if ((localtime)[2] < 12) {
       
Good morning!
     
- } else {
       
Good afternoon!
     
- }
   
%p Current time is: #{DateTime->now->hms}

Route handler:

use DateTime;
   
get '/hello' => sub {
   
template 'hello';
};

More

There are many more interesting templating engines ready to be used with Dancer, such as Mason (provided by Dancer::Template::Mason) or Xslate (Dancer::Template::Xslate). Do a CPAN or MetaCPAN search for "dancer template" to get a list of all the available engines, and choose the one that suits you best. In the true spirit of Perl, there's more than one way to write a template!

This post was originally published as part of the 2011 Dancer Advent Calendar.

9 Comments

Template::Tiny is a great default for Dancer.

I am looking at that Haml code and blech. I am sure some people like it though.

I look at all of these and blech.

(I’ve been using TT, forever, because there wasn’t much else to do at the time, and it makes me blech just as much.)

@Aristotle - Is there one you like?

Robert:

It hit me one day while I was muddling through some template code. It was display logic – it did not belong in a controller or model but really had to be somewhere in the view… and there is no easy way to have it there outside the template. But it is so tedious to do text and data structure munging in TT’s language… there isn’t even a proper map! It would have been so much easier to write in Perl. And the scales fell from my eyes: we have maybe the best text munging language! Why on Earth would we want to use some crippled mini-language in the one part of an app that can most use Perl’s prowess?!

From that day on when I have looked at traditional template systems I have been blind to seeing them for anything else than crappy Turing tar pits.

I had some ideas on how to fix this but my standards on it are very high and some pieces of the puzzle are missing (I’d need to hack around in perlguts to really make it work as I wanted).

And then I saw Template::Semantic, and then HTML::Zoom, which remove various things from my own concepts of the problem and turn out to be a very good idea. Unfortunately the design of the former has a lot of awkward parts and the latter is more or less vapourware. But I have used Template::Semantic in anger, and though it chafes because it is easy to see how it could be so much better, I loved it. I have some ideas for how to improve on its design, which run along the lines of more procedural manipulation (whereas T::S requires you to build up a data structure with selectors in it). There are some modules that try for a jQuery-in-Perl mimicry, and I want to try them first as they may be the ticket – but at least some of them seem more like proof of concept quick-hacks so I’m none too confident I’ll actually find something for me on CPAN. I may have to write it for myself: so be it.

Because I know now what I want. No logic in the templates whatsoever, just plain fragments of HTML filled in by Perl code using selectors. You can easily hand the HTML over to a designer: they do not need special tools, they do not need to learn a new system, they do need to set up a full-blown dev environment, they need nothing that they can’t already do. And the code that fills in the templates is quite straightforward and it’s written in a language fit for the purpose. No mini-languages, no code-and-HTML spaghetti, no glue code that turns business logic data structures into template logic data structures (for bare-bones systems like HTML::Template), no awful crappy mini-language, none of the myriad other warts of doing templates in a more traditional way: just glorious unadulterated Perl for the logic and pure static HTML for the design. Wonderful.

And I must always think of that realisation: that simplicity follows complexity, not the other way around.

Thanks for that.

Me likes HAML. Anything to make my life simpler and less cluttery (though everybody's mileage varies). Who cares if it's not as powerful as Perl, as long as I can be more productive. The same argument has been proposed for C/assembly vs HLL, and in then end aren't we on the later camp?

I doubt you put any thought into that analogy, because as long as we agree that the reason HLLs won is expressiveness, you’ve ended up arguing against yourself. After all, which is more expressive between minilanguages and Perl? Then effectively you are saying your chose assembler over a HLL.

But I shall be no judge of those who like their assembler. I shall just be over here with Perl.

Leave a comment

About Michał Wojciechowski

user-pic I blog about Perl.