Well! I'm so glad you asked. It's a giant pain in the ass because almost all of them do the same things, in the same way. The performance differences among those that are similar are nominal. The syntax is almost always mustaches or ERB-style
<%...%>. Almost none of them run exclusively on the client-side anymore, even those that take a DOM-centric approach to rendering. To try and tease out the subtle differences, I put up a simple GitHub page I hope you good folks will contribute to allowing you to select your priorities and do process of elimination on the existing, supported, non-framework-dependent options.
But, I mean, going and clicking a bunch of little radio buttons is the easy answer. If you don't know where to begin, good enough. I think the more interesting discussion is about what developers need from template engines, and whether they should continue writing new ones. There are a few big criteria I see (and that's what's reflected in the initial version of the tool):speed
It seems like two years or so ago, performance was all anyone cared about. We'd figured out all this shit like loading scripts at the bottom of the page and concatenating everything to make pages load faster and that was the new frontier, motherfuckers. It feels like the pendulum is beginning to swing back the other way now, and I hear people reference Moore's Law more often as justification for things not being super speedy. Complicating things are the way the most modern browsers work. The optimization of traditionally slow approaches flips what we thought we new about performance on its head, so what does "faster" even mean, really? Generally, it means "faster" for your users. It's good to start with the fastest template engine. It's better to optimize for performance the way your users need it.strings or DOMs
Pretty much no template engines deliver a representation of a DOM hierarchy anymore. This is good, because it's objectively, inarguably faster to build a string, not a representation of DOM elements. But what do you do with that rendered string? We can assume naïvely that what we've rendered, once rendered, won't change, but come the fuck on. This is the dynamic web! We're going to have to go fishing through our giant, quickly-rendered string, pull out individual elements, and do stuff to them. Specifically, we're going to have to change their rendering. You could optimize the hell out of your templates so that those child elements have their own templates included as partials in the parent template that renders a larger block, but you are giving yourself an awful lot of credit for organization and diligence if that's your plan. There's really no perfect and sane compromise. It's another one of those things where you need to evaluate how your app will work and how large the chunks of the page suitable for re-rendering can be.religion
But hey, please don't take my word. I'd love it if you played around with the GitHub page, and love it even more if you contributed issues or pull requests to make it more useful. I'd especially love it if you contributed to one of the existing template engines before making your own slightly-different one, cause choosing one is already difficult enough.