If you are using this already, consider changes soon due the discussion around current ESX proposal.
Feel free to keep an eye on udomsay as that will be the implementation reference for consumers.
This is a TC39 proposal and there is a Babel transformer for it too.
There is also a zero-tooling solution based on template litearl tags in this repository, which solves almost all pain-points around having ESX as syntax.
In a quest to explore improvements over common JSX transformers I have managed to find great performance able to compete with template literal based libraries.
In this document I would like to describe, via JS itself, and as PoC, how JSX could be both rebranded as ESX and improved.
Differently from E4X, but also differently from JSX, this proposal leaves developers provide their own "render" implementation, freeing ESX usage from any previous attempt to confine JSX or E4X into the DOM world, where it's been proven, in the JSX case, it's not really where it belongs, as it can be used as neutral, general purpose, DSL.
This document describes all the moving parts of ESX in a way that:
- there is no DOM at all involved, only new primitives introduced by ESX
- all relevant details around each part of the transformation are described through simple objects, here represented as classes instances, but these easily work just as object literals (easy polyfills via transformers)
- no extra scope pollution is needed, hence no
jsxPragma
orjsxFragment
around is required at all (noReact.createElement
orReact.Fragment
needed, norudomsay.interpolation
) - all classes can be used just as types to infer, as oppsite of being really classes ... no clashing in the logic can happen neither. The only global class needed out there is
ESXToken
which carries types and the prototypal inheritance for brand check. - hints to "parse-once" through templates and/or Components are all over the place, making usignal like alternative implementations possible, but also any SSR related project can benefit from these
// base class for instanceof operations
class ESXToken {
static ATTRIBUTE: number;
static INTERPOLATION: number;
static STATIC: number;
static FRAGMENT: number;
static ELEMENT: number;
static COMPONENT: number;
}
// possible `attributes` entry
interface ESXAttribute {
type = ESXToken.ATTRIBUTE;
dynamic: boolean;
name: string;
value: unknown;
}
// possible `attributes` or `children` entry
interface ESXInterpolation {
type = ESXToken.INTERPOLATION;
value: unknown;
}
// possible `children` entry
interface ESXStatic {
type = ESXToken.STATIC;
value: string;
}
// always the same reference when this is used as outer template
interface ESXNode extends ESXToken {
id: object?
children: (ESXStatic | ESXInterpolation | ESXNode)[];
}
// <></>
class ESXFragment extends ESXNode {
type = ESXToken.FRAGMENT;
}
// <any-element />
class ESXElement extends ESXNode {
type = ESXToken.ELEMENT;
name: string;
value: string;
attributes: (ESXAttribute | ESXInterpolation)[];
}
// <AnyComponent />
class ESXComponent extends ESXNode {
type = ESXToken.COMPONENT;
name: string;
value: function;
attributes: (ESXAttribute | ESXInterpolation)[];
get properties(): object?;
}
To better understand what the transformer currently produce, please see this innput and compare it with this output.
There's other ones too:
html
html
The thing is, we can standardize syntax, but I don't think anyone is confident of which runtime implementation is the best yet.
Plus I personally don't think that this belongs in JavaScript spec. JavaScript is not specifically about making trees (namely DOM trees). I think a spec like this might make more sense as part of browser DOM API specs. I think it would be a lot more likely for a browser to standardize some sort of
html
template string language.I just don't think that ECMAScript itself is likely to be the carrier of this feature, because it is very specific compared to other APIs (f.e.
Math.whatever
is an stdlib that is highly useful in many generic cases, not just tree building, and a language aims to be very generic).Maybe WICG.io would be a better place to propose this (but I still think runtime semantics would currently hold it back). I like Solid.js
html
better than Lithtml
andesx
, for example. I like the way that it works. But that's just my taste.It will take a lot of time to see what's really the best runtime.