Web apps of course have to somehow produce HTML from the underlying data. In this sense, template engines are immortal. There are however many ways to express this transformation of data into HTML and not all of them work so well.
Template engines obviously process templates, but what is a template? Traditionally, template is a HTML fragment with some embedded code. Complexity of the embedded code ranges from simple variable references to interleaving of the template with full programming language.
Variables are super simple, but they are seldom sufficient. More power is needed. So template engines add more and more programming constructs (paths, loops, conditions, functions, ...) and end up duplicating features of programming languages while never quite reaching their expressiveness.
Pushing this to the extreme, some template engines interleave HTML with an actual programming language. One might think this will get us expressiveness of programming language while keeping things simple in constant parts of the document.
Not quite. It turns out the constant parts of the template are quite repetitive. So more and more utility functions are added to help generate the repetitive parts and to enforce consistency in site style. We then end up with something that looks more like content embedded in code rather than code embedded in text.
One has to admit this is no longer a template, at least not in the traditional sense. It's code with plenty of inline content. So why pay the cost of using template engine? It's better to just use standard programming language and put content in strings.
Of course, there's still a lot of HTML. But that can be handled with a nice library that maps HTML into the language as library API. It's really not that much overhead if the API is cleverly designed.
If there's a longer piece of text/content, one can still use some template engine to process it, as long as said template engine can be embedded in code via plain library call. It is even possible to mix several template engines and markup languages on the same page.
So for example, app code generates some statistic, which is then formatted according to app standards and embedded via variable into a short template, which contains a paragraph of text. After substitution, this short template becomes Markdown code, which is then rendered into HTML. All this on single page. Neat. Everything is just a function call away.
Of course, you can say pages coded in this way are still templates in some sense. And you are technically right. But there's no template engine. Just standard programming language. You get structuring features and expressiveness of a programming language plus unfettered access to libraries. No half-baked template engine standing in your way.
Some people argue that templates, or code-behind as it's sometimes called, allow UI designers to work on the template without dealing with complexity of application code. But how many projects actually operate like this? And is it really easier to write and debug templates than code? There are surely way better tools for authoring and debugging code.
So no template engines for me. All my dynamic pages are going to be 100% code with content inlined where necessary. This is the approach I am going to take with my PushMode library. Java already has multi-line strings. I am looking forward to JEP 430 string templates, which can really tidy up longer template strings.