80% of my coding is doing this (or why templates are dead)
OK. Maybe not 80%. Maybe 50%. It’s hard to say.
But a large chunk of my coding life has been dedicated to one task: writing code in one language (say Java or JavaScript) whose sole purpose is to generate a different language (say HTML).
This is such a huge part of my world, that I’m surprised the makers of programming languages don’t do a better job addressing this.
But given how much time we spend on this task, it’s worth a little thought as to how to do it most productively.
Below is my opinion for the best way to generate HTML in 2017 along with some context.
Technique #1: String Building
My first ever web app was a Java Servlet. It was mostly a bunch of Java code whose sole purpose was to generate a giant HTML string.
Many JavaScript apps are structured similarly. You build up a big string of HTML and then use innerHTML to plunk it onto your page.
But string building has lots of problems. It can be hard to read with all of the quotes-in-quotes and escaping that is needed. And it’s error prone. Things inside of a string are generally not checked by the compiler or linting tool. There is no type safety. Refactoring is almost impossible. And IDE support inside of a string is usually not so great **. And there is also the security concern regarding injection.
** JetBrains actually does some pretty amazing things in this area.
Technique #2: Imperative Tree Building
Next we have tree-building libraries and APIs. The most popular is the one built into the browser: the DOM API. This is where you build up an HTML tree by making repeated calls to createElement
and appendChild
.
This too has lots of problems. For one, it leads to really verbose code. Also it’s difficult to visualize the tree structure you are creating by looking at the code. And there are lots of string identifiers in the code that are not checked by the compiler or linting tools.
Technique #3: Template Languages
The most popular approach for solving the above mentioned problems is the template language.
The first one I ever used was JSP. I have since used dozens of these tools. Some run on the server. Some run on the client. Some execute at runtime. Others execute as part of a build step. The most popular template language today is probably Angular JS.
[Warning: Possibly controversial statements coming up. No offense to users of templating languages].
Here is the problem with template languages.
At some point, you will need to conditionally render some piece of content, i.e. only show some snippet of html if such and such is true. So the template language will need something that looks like an if statement. Or perhaps its a large number of conditions all revolving around a single value. So the template language will need something akin to a switch.
Then you will likely need to present some lists or tables. So the template language will need some kind of looping construct.
Eventually your templates will grow large. So you’ll need some way organize them, break them down into smaller pieces. Some way for one template to call another template. Some way to define reusable chunks of template code. The template language will need constructs for all of this.
And then you’ll need some way to format numbers and dates.
And so on.
Overtime, most template languages eventually reinvent practically every feature of a general purpose programming language.
And that’s what template languages really are. They are programming languages. Usually bad programming languages.
So now you have to know the host language (Java or JavaScript); you have to know the language you are generating (HTML); and you have to know this other thing, the template language, which is itself practically a full-blown programming language.
And with templates, you have many of the same problems you have with string building: Things in a template are often not checked by the compiler or linting tool. There is less type safety. Refactoring is risky. Less IDE help.
Technique #4: Internal DSLs
Internal DSL’s are, in my opinion, the best solution. They solve all of problems mentioned above.
DSL stands for Domain Specific Language. In our story, the DSL is HTML. An internal DSL refers to the host programming language’s ability to express that DSL using just the host language (with no string building).
One could argue that Internal DSLs are not really a separate technique from #2 (Tree Building) and #3 (Templates). In fact, internal DSLs could be described as a less-crappy tree building API. Or as a templating language that is more integral to the host language.
But I think the technique is different enough to deserve it’s own category.
Below, I’ll describe the two internal DSLs that I use every day for generating HTML.
But first a note about separation of concerns.
Separation of Concerns
There is a programming maxim that says you should separate concerns. The two concerns pertaining to this conversation are UI logic and business logic. Separating UI logic from business logic is, in my opinion, good advice.
But sometimes this piece of wisdom gets misconstrued as: you should not mix your html with your host language. Or you shouldn’t mix curly braces (Java/JavaScript) with angle braces (HTML).
String Building and Tree Building totally mix html with the host language. You might have noticed when I was listing all of the problems associated with String Building and Tree Building, I never mentioned “mixing curly braces with angle braces” as one of those problems. That’s because I don’t think it is a problem.
It is totally possible and easy to create HTML apps using String Building or Tree Building or Internal DSLs that keep your concerns separate. And that is a distinctly different and more useful objective than “not mixing curly braces with angle braces”.
So in short, separation of concerns is not a valid reason to choose or not to choose any of the 4 techniques discussed.
Internal DSL #1: JSX
JSX is an extension of the JavaScript programming language that adds native support for XML (and thus HTML). The easiest way to get JSX is to use React. But there are other frameworks that support JSX as well. Here is what it looks like:
function buttonBar(x1,x2,x3){
return <div>
<button>{x1}</button>
<button>{x2}</button>
<button>{x3}</button>
</div>
}
If you need branching, you would use JavaScript’s if
or switch.
Or the ternary operator. If you want looping, use JavaScript’s looping constructs. If you want to organize your UI code, use JavaScript constructs like functions, classes and modules. If you want to create a reusable UI component, create a function. If you want to parameterize your UI component, use JavaScript function arguments.
The above code gets transpiled into a bunch of nested createElement
function calls. So this is really just an improvement on Technique #2: Tree Building.
Also, you may have noticed that the above code looks a bit like a template. Despite, the click bait title of my post, we aren’t really doing away with templates. Just making it a more integral part of the host language.
Internal DSL #2: Kotlin HTML
Kotlin is a programming language from JetBrains, the maker of many popular IDE’s and editors. It is statically typed and concise. It compiles to JavaScript and to Java byte code. Thus the snippet of code I’m about to show you can run on the client (like angular) or on the server (like JSP).
Here is the same button bar in Kotlin:
fun buttonBar(x1: String, x2: String, x3: String) = doc.create.div {
button { +x1 }
button { +x2 }
button { +x3 }
}
I like this because Kotlin is statically typed. That means you get all of the benefits of type checking, like IDE autocompletion and refactoring support:

Kotlin calls this a type-safe builder (an html builder in this case).
Other Internal DSLs for UI Building
I just described the two internal DSLs that I use every day for HTML tree building.
Here are some other frameworks and/or languages that have eschewed templates in favor of internal DSLs for HTML (or UI) tree building:
- Elm. Elm is a compile-to-JS language and also a web framework. It uses an internal DSL (basically nested function calls) to generate all of it’s HTML.
- Hyperscript. Hyperscript is a concise JavaScript API/DSL for generating the HTML tree using nested function calls.
- Groovy. The Groovy language has been using HTML builders (similar to Kotlin) for years.
- Om. Om is the de facto web framework for the Clojurescript language. Like, Elm, it uses an internal DSL of nested function calls to generate HTML.
- JavaFX Script. This falls under the category of “super interesting technology — but dead on arrival due to bungled marketing by Sun.” But it deserves special mention because it was the first time I ever used an internal DSL for building a UI. After using JavaFX script, I began asking the question: why aren’t all UI’s built like this? This was also the most elegant UI tree building DSL I have ever seen. It’s a shame that Sun killed it.
- Flutter. This is a new cross platform mobile UI framework from Google. It has no external XML/HTML file for describing the UI. Instead the entire UI tree is built using an internal DSL (basically a tree of constructor calls).
- Anko Layouts. This is a Kotlin internal DSL for building an Android UI tree. It replaces Android’s XML-based external DSL. Anko may be the best thing to ever happen in the area of Android UI programming.
Conclusion
Obviously, it’s possible to create HTML apps using any of the 4 techniques mentioned above. But I have spent 1000s of hours using each. And for me, Technique #4, Internal DSL, is the most flexible and most productive.
Dave Ford is a developer, trainer and consultant specializing in Java, JavaScript, Kotlin and React. He is the author of Kotlin Quick Start for Java Developers , an online course published on Udemy. He offers instructor-led React and Kotlin training through his training company, Smart Soft.