You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TL;DR: I think we need a better template format for our form.io components. In this issue I'm attempting to work through the benefits and downsides of what we have and investigate other options.
I've been thinking a lot lately about how painful our EJS(-ish) templates, which we inherited from formio.js, are to edit. EJS is certainly one of, if not the, most minimal templating "languages", and the biggest advantage that it has over other languages is the lack of a runtime. For example, this:
However, EJS has some authoring "ergonomics" issues. It quickly gets illegible when you start wrapping control structures (if, else, for loops, etc.) around the output directives ({{ output }}), especially with formio.js's choice of Django/Jinja/Nunjucks-style delimiters ({% %} instead of <% %>):
{% if (title) { %}
<h1>{{ title }}</h1>
{% } %}
I get a headache just looking at it; there are just too many curly braces, and there's no syntax highlighter that understands it. Compare the Django/Jinja/Nunjucks equivalent, which GitHub and any text editor worth its salt know how to syntax-highlight:
{%iftitle%}
<h1>{{ title }}</h1>
{%endif%}
Twig
Twig templates have a very similar syntax, and the benefit of using a common template format is that we could possibly share "components" (templates) between this repo and sf.gov. However, while the ergonomics of the template syntax are nice, the runtime alone weighs ~26K gzipped. In other words, we'd have to bring along 26K just to render the templates at runtime, whereas EJS "compiles down" to just a plain old JavaScript function that returns a string.
I don't know that we gain enough from using Twig to justify a 26K (+40% compared to the current 65K) bundle size increase.
JSX
Over in #107 I attempted to see what using JSX syntax as a template format, but with a lightweight string renderer called vdo in place of the React runtime. The gist is that this:
exportdefaultprops=><h1>{props.title}</h1>
Gets compiled into:
const{createElement: h}=require('vdo')// this gets hoisted elsewheremodule.exports=props=>h('h1',null,[props.title])
And the h() function just returns the HTML string representation of the element, as in:
The vdo runtime weighs in at ~1K. You can see in this comment that with a couple of templates translated to JSX and vdo in the mix, the bundle is ~3K (4%) larger. I think that if we were to convert the rest of our templates to JSX the bundle would end up smaller. (Imagine every out+='...' statement replaced by a nested h('div', ...) call, attributes expressed as JS object literals, shorter conditionals, etc.)
Anyway, more here in the near future!
The text was updated successfully, but these errors were encountered:
Side note: in #107 I first experimented with vdo, but jsx-pragmatic appears to be a better option. It's been updated recently, and supports fragments (and the more concise <>{some}{content}</> syntax) out of the box (vdo does not, and requires some hacky compiler-level workarounds). There's an additional render step involved in jsx-pragmatic, which means that we'd need to write our templates like this:
TL;DR: I think we need a better template format for our form.io components. In this issue I'm attempting to work through the benefits and downsides of what we have and investigate other options.
I've been thinking a lot lately about how painful our EJS(-ish) templates, which we inherited from formio.js, are to edit. EJS is certainly one of, if not the, most minimal templating "languages", and the biggest advantage that it has over other languages is the lack of a runtime. For example, this:
Is compiled into something like this:
However, EJS has some authoring "ergonomics" issues. It quickly gets illegible when you start wrapping control structures (if, else, for loops, etc.) around the output directives (
{{ output }}
), especially with formio.js's choice of Django/Jinja/Nunjucks-style delimiters ({% %}
instead of<% %>
):I get a headache just looking at it; there are just too many curly braces, and there's no syntax highlighter that understands it. Compare the Django/Jinja/Nunjucks equivalent, which GitHub and any text editor worth its salt know how to syntax-highlight:
Twig
Twig templates have a very similar syntax, and the benefit of using a common template format is that we could possibly share "components" (templates) between this repo and sf.gov. However, while the ergonomics of the template syntax are nice, the runtime alone weighs ~26K gzipped. In other words, we'd have to bring along 26K just to render the templates at runtime, whereas EJS "compiles down" to just a plain old JavaScript function that returns a string.
I don't know that we gain enough from using Twig to justify a 26K (+40% compared to the current 65K) bundle size increase.
JSX
Over in #107 I attempted to see what using JSX syntax as a template format, but with a lightweight string renderer called vdo in place of the React runtime. The gist is that this:
Gets compiled into:
And the
h()
function just returns the HTML string representation of the element, as in:The vdo runtime weighs in at ~1K. You can see in this comment that with a couple of templates translated to JSX and vdo in the mix, the bundle is ~3K (4%) larger. I think that if we were to convert the rest of our templates to JSX the bundle would end up smaller. (Imagine every
out+='...'
statement replaced by a nestedh('div', ...)
call, attributes expressed as JS object literals, shorter conditionals, etc.)Anyway, more here in the near future!
The text was updated successfully, but these errors were encountered: