ultraq / thymeleafjs

A basic implementation of the Thymeleaf templating engine in JavaScript
Apache License 2.0
52 stars 8 forks source link

Ideas for making the isomorphic templating experience better #13

Open ultraq opened 6 years ago

ultraq commented 6 years ago

From working on thymeleaf-js-todo and especially with trying to get Thymeleaf templates working on both client and server side ("isomorphic templates"), I often encounter some "why should it be like this?" or "if I had this then it'd be better!" moments that might be good improvements that can be made to this project to improve the developer experience.

Read th processors by default, but override if an equivalent thjs one is encountered

This idea comes from the difference in Java and JavaScript, eg: to get the size of a list in Java (list.size()) vs JavaScript (list.length). You can only really put one inside an attribute processor, which then makes the language not understand it.

One idea was that I could put both on an element, eg:

<section th:if="${list.size() > 0}" thjs:if="${list.length}">

That seems reasonable to me, but on templates where the expression language for an item is the same, you end up duplicating the same code, eg:

<div th:text="${item.value}" thjs:text="${item.value}">

So why not make it listen to th by default, but if it encounters a thjs one then use that?

To make that work, we'd need a way to configure both default and overridable prefixes, with a smart default of probably th followed by thjs.

A module/library for making Java/JavaScript "match"

This can only be applied to Groovy projects (via module extensions), so likely the only "reasonable" one would be to modify JavaScript (via prototype modification) so that it works in Java too. The idea behind this is to consolidate the differences between the client and server languages so that the same expression can be used either side, eg:

<section th:if="${list.size() > 0}">

And then that becomes readable in JS as well.

I'm not such a fan of this idea because the JS community threw out the idea of modifying prototypes a long time ago because of the unintended side-effects it had on the maintainability of code.

Keep the isomorphic templating stuff separate

So what I had for Thymeleaf JS worked pretty well already if the only language on both client and server was JS (barring the lack of th:fragment support!). If I continue to grow things so that it can meet the isomorphic templating use case, it might make this module balloon to much larger sizes. It might be better to make sure this project acts as a good base for an additional "compatibility w/ original Thymeleaf" module to fill in all the gaps.


(More to come as I continue using Thymeleaf JS in projects.)

ultraq commented 5 years ago

Intercept processing during the execution phase of parsing expressions

Similar to the "make java/javascript match" idea, except add hooks / extension points that can spot calls to known Java methods and redirect them to their JS equivalents, eg: if size() is encountered, redirect it to the length property.

This idea is good for not requiring developers to write things out twice.

Ideally, this functionality could also be added to a separate module (combining with the "keep the isomorphic stuff separate" idea) so that it can be an opt-in feature. To achieve that though, I'd have to expand the template engine configuration so that these "hooks" can be configurable.