Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Last active October 18, 2024 10:55
Show Gist options
  • Save WebReflection/71aed0c811e2e88e3cd3c647213f0e6c to your computer and use it in GitHub Desktop.
Save WebReflection/71aed0c811e2e88e3cd3c647213f0e6c to your computer and use it in GitHub Desktop.

Revisions

  1. WebReflection revised this gist Jun 23, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -236,7 +236,7 @@ However, I've been using [attributechanged](https://github.com/WebReflection/att

    I don't know, but you like events more, like I do, I can suggest also to have a look at [disconnected](https://github.com/WebReflection/disconnected#readme), which brings `onconnected` and `ondisconnected` events to any DOM element, including Custom Elements.

    These two are part of the core of [hyperHTML](https://github.com/WebReflection/hyperHTML), and [lighterhtml-plus](https://www.npmjs.com/package/lighterhtml-plus), while at least for boolean values, [HyperHTMLElement](https://github.com/WebReflection/hyperHTML-Element) offers a `observedBooleans` extra getter.
    These two are part of the core of [hyperHTML](https://github.com/WebReflection/hyperHTML), and [lighterhtml-plus](https://www.npmjs.com/package/lighterhtml-plus), while at least for boolean values, [HyperHTMLElement](https://github.com/WebReflection/hyperHTML-Element) offers a `booleanAttributes` extra getter.

    Last, but not least, [🔥 heresy 🔥](https://github.com/WebReflection/heresy) backes almost the best of all these libraries, providing events out of the box, and some other utility borrowed here and there.

  2. WebReflection revised this gist Jun 22, 2019. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -83,6 +83,12 @@ Accordingly, since custom elements builtins are possible, is there any other arg

    Is there anything more semantic and lightweight out there? (beside [wickedElements](https://github.com/WebReflection/wicked-elements#readme), of course)

    ### Even Better SSR

    With little helpers such as [heresy-ssr](https://github.com/WebReflection/heresy-ssr), you can serve clean components with rehydration on the client that costs 0.

    Check the repository out, then `npm run build` then `node test/twitter-share.js` and see the clean SSR component delivered, and rehydrated later on through the client side definition.


    ## 2. CSS maybe in JS

  3. WebReflection revised this gist Jun 21, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -73,7 +73,7 @@ It could also have a fallback `href` in case things go really wrong, or such `hr
    <a is="twitter-share" href="....">Tweet this</a>
    ```

    That'd be automatically hydrated on the client, once the component is registered, and the functionality is presered, 'cause no observable attributes are used.
    That'd be automatically hydrated on the client, once the component is registered, and the functionality is preserved, 'cause no observable attributes are used.

    [You can try above example in Code Pen](https://codepen.io/WebReflection/pen/LKWyLB?editors=0010).

  4. WebReflection revised this gist Jun 21, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -81,7 +81,7 @@ There's the possibility to have the magic svelte-class too, because indeed that'

    Accordingly, since custom elements builtins are possible, is there any other argument against Custom Elements and progressive enhancement, since these also provide automatic hydration when rendered through the server?

    Is there anything more semantic and lightweight out there? (beside wickedElements, of course)
    Is there anything more semantic and lightweight out there? (beside [wickedElements](https://github.com/WebReflection/wicked-elements#readme), of course)


    ## 2. CSS maybe in JS
  5. WebReflection revised this gist Jun 21, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -35,8 +35,8 @@ customElements.define(
    static get observedAttributes() {
    return ['text', 'url', 'hashtags', 'via', 'related'];
    }
    connectedCallback() { this.addEventListener('click', this); }
    attributeChangedCallback() {
    this.addEventListener('click', this);
    this.setAttribute('noreferrer', '');
    this.textContent = 'Tweet this';
    this.href = 'https://twitter.com/intent/tweet?' +
  6. WebReflection revised this gist Jun 21, 2019. 1 changed file with 36 additions and 19 deletions.
    55 changes: 36 additions & 19 deletions why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -29,42 +29,59 @@ The _TL;DR_ answer is that **yes, you can extend builtin elements**, and I have
    Here you go:

    ```js
    const shared = [];
    customElements.define(
    'twitter-share',
    class extends HTMLAnchorElement {
    connectedCallback() {
    // use a default _blank target
    this.target = this.target || '_blank';
    class TwitterShare extends HTMLAnchorElement {
    static get observedAttributes() {
    return ['text', 'url', 'hashtags', 'via', 'related'];
    }
    attributeChangedCallback() {
    this.addEventListener('click', this);
    this.setAttribute('noreferrer', '');
    this.textContent = 'Tweet this';
    this.href = 'https://twitter.com/intent/tweet?' +
    getQueryString(this, TwitterShare.observedAttributes);
    }
    handleEvent(e) { this[`on${e.type}`](e); }
    onclick() {
    const {href} = this;
    if (!shared.includes(href)) {
    // notify once the counter
    shared.push(href);
    fetch(`/share-counter?href=${encodeURIComponent(href)}`);
    }
    handleEvent(e) { this['on' + e.type](e); }
    onclick(e) {
    e.preventDefault();
    const w = 600;
    const h = 400;
    const x = (screen.width - w) / 2;
    const y = (screen.height - h) / 2;
    const features = `width=${w},height=${h},left=${x},top=${y}`;
    window.open(this.href, '_blank', features);
    }
    },
    {extends: 'a'}
    );
    ```

    Now the component in the page can look the same:
    Now the component in the page can just be a link:

    ```html
    <a is="twitter-share" noreferrer href="...">
    Tweet this
    </a>
    <a is="twitter-share"
    text="A Twitter share button with progressive enhancement"
    url="https://codepen.io/WebReflection/pen/LKWyLB?editors=0010"
    via="webreflection"
    />
    ```

    It could also have a fallback `href` in case things go really wrong, or such `href` could be generated directly on the server, so that the client will receive just:

    ```html
    <a is="twitter-share" href="....">Tweet this</a>
    ```

    That'd be automatically hydrated on the client, once the component is registered, and the functionality is presered, 'cause no observable attributes are used.

    [You can try above example in Code Pen](https://codepen.io/WebReflection/pen/LKWyLB?editors=0010).

    There's the possibility to have the magic svelte-class too, because indeed that's just a link, and svelte can use the link.

    Since custom elements builtins are possible, is there any other argument against Custom Elements and progressive enhancement, since these also provide automatic hydration when rendered through the server?
    Accordingly, since custom elements builtins are possible, is there any other argument against Custom Elements and progressive enhancement, since these also provide automatic hydration when rendered through the server?

    Is there anything more semantic and lightweight out there?
    Is there anything more semantic and lightweight out there? (beside wickedElements, of course)


    ## 2. CSS maybe in JS
  7. WebReflection revised this gist Jun 21, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ Let's start by defining what we are talking about.

    ### The Web Components Umbrella

    As you can read in the [dedicated GitHub page](https://github.com/w3c/webcomponents#web-components), Web Components is a group of features, where each feature works already by itself.
    As you can read in the [dedicated GitHub page](https://github.com/w3c/webcomponents#web-components), Web Components is a group of features, where each feature works already by itself, and it doesn't need other features of the group to be already usable, or useful.

    You don't need to use all the Web Components features to create, and ship, robust Custom Elements for your project, or in the wild, you need to understand all parts are unrelated.

  8. WebReflection revised this gist Jun 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -13,7 +13,7 @@ You don't need to use all the Web Components features to create, and ship, robus

    * _Shadow DOM works for every node already_, you don't need Custom Elements to use it, it's a spec a part
    * _Custom Elements work everywhere already_, and you don't need Shadow DOM to define custom elements
    * _HTML Templates_ are super useful nodes, and not only already parked in the layout. Every library dealing with runtime DOM creation ues these to reliably create any sort of DOM node. And you don't need even this to have Custom Elements.
    * _HTML Templates_ are super useful nodes, and not only already parked in the layout. Every library dealing with runtime DOM creation uses these to reliably create any sort of DOM node. And you don't need even this to have Custom Elements.
    * _CSS changes_ are not fully there yet but it doesn't matter. If your project works without custom elements but with reliable styling, you can apply the exact same toolchain/technique to Custom Elements: they are literally just elements!
    * _HTML Modules_ are also not too interesting yet, as I believe module mapping would gain more traction. And yet, you don't need _HTML Modules_ to ship Custom Elements.

  9. WebReflection revised this gist Jun 20, 2019. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -215,7 +215,7 @@ I don't know, but you like events more, like I do, I can suggest also to have a

    These two are part of the core of [hyperHTML](https://github.com/WebReflection/hyperHTML), and [lighterhtml-plus](https://www.npmjs.com/package/lighterhtml-plus), while at least for boolean values, [HyperHTMLElement](https://github.com/WebReflection/hyperHTML-Element) offers a `observedBooleans` extra getter.

    Last, but not least, [🔥 heresy 🔥](https://github.com/WebReflection/hyperHTML) backes almost the best of all these libraries, providing events out of the box, and some other utility borrowed here and there.
    Last, but not least, [🔥 heresy 🔥](https://github.com/WebReflection/heresy) backes almost the best of all these libraries, providing events out of the box, and some other utility borrowed here and there.


    ## 8. The DOM is not that bad
    @@ -290,7 +290,7 @@ This is where we indeed agree, but for a different conclusion:
    * Custom Elements are already usable everywhere
    * Custom Elements builtin exist natively, and are nicely supported by the right polyfills
    * you don't need the complex parts of Web Components if you just need some custom element
    * you don't need to simulate 1:1 JSX, but you can get pretty closer already with _herey_, _hyperHTML_, or plain _lighterhtml_, which are ale developed via standards, in JavaScript, and need zero toolchain, hence their components are widely distributable in the wild, or surely never too heavy for your own project.
    * you don't need to simulate 1:1 JSX, but you can get pretty closer already with _heresy_, _hyperHTML_, or plain _lighterhtml_, which are ale developed via standards, in JavaScript, and need zero toolchain, hence their components are widely distributable in the wild, or surely never too heavy for your own project.

    Please give Custom Elements a better chance, they don't deserve to be put in shame due other parts of the specs.

  10. WebReflection revised this gist Jun 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -285,7 +285,7 @@ render(document.documentElement, html`<Body />`);

    ## 10. These are all solved problems

    This is were we indeed agree, but for a different conclusion:
    This is where we indeed agree, but for a different conclusion:

    * Custom Elements are already usable everywhere
    * Custom Elements builtin exist natively, and are nicely supported by the right polyfills
  11. WebReflection revised this gist Jun 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -220,7 +220,7 @@ Last, but not least, [🔥 heresy 🔥](https://github.com/WebReflection/hyperHT

    ## 8. The DOM is not that bad

    I might be too old here, but I think the DOM these days is surely styll not immediate to grasp, but awesome enough to support the explosion of libraries, utilities, and frameworks on top of it, which are all different, and mostly blazing fast, despite all those indirections/
    I might be too old here, but I think the DOM these days is surely still not immediate to grasp, but awesome enough to support the explosion of libraries, utilities, and frameworks on top of it, which are all different, and mostly blazing fast, despite all those indirections/

    Classifying the DOM as categorically _bad_ doesn't really seem fair.

  12. WebReflection revised this gist Jun 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -294,4 +294,4 @@ This is were we indeed agree, but for a different conclusion:

    Please give Custom Elements a better chance, they don't deserve to be put in shame due other parts of the specs.

    THanks for reading.
    Thanks for reading.
  13. WebReflection revised this gist Jun 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -218,7 +218,7 @@ These two are part of the core of [hyperHTML](https://github.com/WebReflection/h
    Last, but not least, [🔥 heresy 🔥](https://github.com/WebReflection/hyperHTML) backes almost the best of all these libraries, providing events out of the box, and some other utility borrowed here and there.


    ## 8. The DOM is bad
    ## 8. The DOM is not that bad

    I might be too old here, but I think the DOM these days is surely styll not immediate to grasp, but awesome enough to support the explosion of libraries, utilities, and frameworks on top of it, which are all different, and mostly blazing fast, despite all those indirections/

  14. WebReflection created this gist Jun 20, 2019.
    297 changes: 297 additions & 0 deletions why-i-use-web-components.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,297 @@
    # Why I use web components

    This is some sort of answer to recent posts regarding Web Components, where more than a few misconceptions were delivered as fact.

    Let's start by defining what we are talking about.


    ### The Web Components Umbrella

    As you can read in the [dedicated GitHub page](https://github.com/w3c/webcomponents#web-components), Web Components is a group of features, where each feature works already by itself.

    You don't need to use all the Web Components features to create, and ship, robust Custom Elements for your project, or in the wild, you need to understand all parts are unrelated.

    * _Shadow DOM works for every node already_, you don't need Custom Elements to use it, it's a spec a part
    * _Custom Elements work everywhere already_, and you don't need Shadow DOM to define custom elements
    * _HTML Templates_ are super useful nodes, and not only already parked in the layout. Every library dealing with runtime DOM creation ues these to reliably create any sort of DOM node. And you don't need even this to have Custom Elements.
    * _CSS changes_ are not fully there yet but it doesn't matter. If your project works without custom elements but with reliable styling, you can apply the exact same toolchain/technique to Custom Elements: they are literally just elements!
    * _HTML Modules_ are also not too interesting yet, as I believe module mapping would gain more traction. And yet, you don't need _HTML Modules_ to ship Custom Elements.

    Now, following [the most recent post I've read on this argument](https://dev.to/richharris/why-i-don-t-use-web-components-2cia), but it's similar to [other posts](https://twitter.com/WebReflection/status/1138501634953269253) recently published here and there, I'd like to address all points.


    ## 1. Progressive enhancement

    The _TL;DR_ answer is that **yes, you can extend builtin elements**, and I have no idea for how many years I've shouted that.

    > In other words, a bog-standard `<a>` element, in all its accessible glory.
    Here you go:

    ```js
    const shared = [];
    customElements.define(
    'twitter-share',
    class extends HTMLAnchorElement {
    connectedCallback() {
    // use a default _blank target
    this.target = this.target || '_blank';
    this.addEventListener('click', this);
    }
    handleEvent(e) { this[`on${e.type}`](e); }
    onclick() {
    const {href} = this;
    if (!shared.includes(href)) {
    // notify once the counter
    shared.push(href);
    fetch(`/share-counter?href=${encodeURIComponent(href)}`);
    }
    }
    },
    {extends: 'a'}
    );
    ```

    Now the component in the page can look the same:

    ```html
    <a is="twitter-share" noreferrer href="...">
    Tweet this
    </a>
    ```

    There's the possibility to have the magic svelte-class too, because indeed that's just a link, and svelte can use the link.

    Since custom elements builtins are possible, is there any other argument against Custom Elements and progressive enhancement, since these also provide automatic hydration when rendered through the server?

    Is there anything more semantic and lightweight out there?


    ## 2. CSS maybe in JS

    > If you want to use Shadow DOM for style encapsulation ...
    While I hope it's clear by now nobody needs Shadow DOM to style components, there are many other ways to better style any layout without needing Shadow DOM.

    Not only Svelte is compatible out of the box with nested styles, where I work we also have various [io-prefixed Custom Elements](https://gitlab.com/eyeo/adblockplus/abpui/adblockplusui/tree/master/js) (no shadow dom, no modules, just definitions via [HyperHTMLELement](https://github.com/WebReflection/hyperHTML-Element#hyperhtml-element)), and all of them with their own [css files](https://gitlab.com/eyeo/adblockplus/abpui/adblockplusui/tree/master/css), with bundling taking care of the rest: CSS in style, JS in script.

    However, even a generic Custom Element could do the same: contain its own CSS definition, and still use the whole document to inject the proper style, when and if needed, instead of letting the server do that.

    With this technique the CSS might be included in the Custom Element, but it will also enable CSS on demand, once per custom element definition, as example, so that you don't need the bloat of every component upfront: you can just download these on demand and see the style applied at distance.

    I know this also the general purpose of _HTML Modules_, but all I wanted to say is that we already have the ability to bundle Custom Elements together with their style, if needed, and their HTML or SVG content, something easily provided by my libs, such as [lighterhtml](https://github.com/WebReflection/lighterhtml/#readme) or its booster [heresy](https://github.com/WebReflection/heresy/#readme), but also by many others.


    ## 3. Platform fatigue

    I am often disappointed by the way new features are presented, specially if advertised prematurely without other vendors consensus, as it was for Custom Elements V0, which surely didn't help the Web Components Umbrella shine.

    However, what we have now, is the ability to use Custom Elements V1 everywhere, and this is huge!!!

    Not only [my polyfill from 2014](https://github.com/WebReflection/document-register-element) worked in every IE8+ and mobile browser out there, without native `customElements`, but today all we optionally need is [builtin extends in Safari](https://github.com/ungap/custom-elements-builtin#readme), and none of these two poly will ever land in evergreen Chrome, Firefox, or Edge on Chrome.

    ```html
    <script>
    if (this.customElements) {
    try {
    // Safari fails here 'cause they poisoned every native constructor
    customElements.define('built-in', document.createElement('p').constructor, {'extends':'p'});
    } catch(_) {
    // This will land only in Safari, until they fix their gap with others
    // The poly is ~1K and based on native Custom Elements V1 API
    document.write('<script src="//unpkg.com/@ungap/custom-elements-builtin"><\x2fscript>');
    }
    } else {
    // legacy browsers only, including: IE8, IE9, IE10, IE11, MSEdge and very old mobile phones
    document.write('<script src="//unpkg.com/document-register-element"><\x2fscript>');
    }
    </script>
    <script>
    // everything else that needs a reliable customElements global
    // with built-in extends capabilities
    </script>
    ```

    That is it: it's zero bloat for 70% of the users, ~1K extra bloat for Safari devices until builtin extends are in, and still few Ks for legacy only, perfectly capable of working with custom elements too 🎉

    So, considering the features already shipped, and [polyfills cover everything since 2014](https://github.com/WebReflection/document-register-element#tested-on) or before, why don't we start using Custom Elements instead of keep demanding new features?


    ## 4. Polyfills

    This is probably one of the most controversial parts of the whole Web Components history:

    * the Shadow DOM polyfill is IMO not worth it, if you want a spec compliant Shadow DOM. It's not by accident that all my polyfills are about what's possible to polyfill, which is Custom Elements V0 and V1. Indeed you likely don't want to deal with Shadow DOM polyfills, and for (maybe) the last time: Shadow DOM is not needed to create, or deliver, custom elements!
    * however, if you want a non standard Shadow DOM, you don't need more than 1.4K to [have it down to IE9](https://github.com/WebReflection/attachshadow#readme)
    * but if you target mobile, or even less than IE 11, you're way [better off with my polyfill](https://github.com/WebReflection/document-register-element), the one used in these years by Google AMP or AFrame. No, it doesn't provide Shadow DOM, because it's a different specification/part of the Web Components umbrella.
    * if you target evergreen browsers, all you need to go full steam is feature detect Safari and [load the right poly](https://github.com/ungap/custom-elements-builtin#readme)

    ### ... why everything you link sounds like ... different?

    When you have some Web standards advocate with _[NIH](https://en.wikipedia.org/wiki/Not_invented_here)_ syndrome, it's difficult to get a spot in other articles and projects.

    However, you'll find the other polyfill links literally everywhere else, so I'll reserve this gist for my contribution, 'hope you don't mind.


    ## 5. Composition

    I am not sure what is the issue presented in there, 'cause I don't see how any other non live solution would work differently, whatever content supposed to land on that toggle/slot.

    If the difference is that some automation might place DOM nodes live only on toggles, the same automation could do exactly what it does with custom elements too.

    Moreover, in my real-world experience with Custom Elements, composing is exactly what makes CE amazing!

    Regardless, do you know what's the issue with that element? Its [attributeChangedCallback](https://github.com/justinfagnani/html-include-element/blob/master/html-include-element.js#L73-L103) doesn't check if the node itself is live, and visible, or not, which is nothing that terrible to eventually solve, even on user-land:

    ```html
    <details ontoggle="
    var hi = this.querySelector('html-include');
    if (!hi.src)
    hi.src = hi.dataset.src;
    ">
    <summary>Toggle the section for more info:</summary>
    <toggled-section>
    <html-include data-src="./more-info.html"/>
    </toggled-section>
    </details>
    ```

    Beside the "_Oh My Gosh, JS in HTML_" heresy, written just to keep it simple, you can see having to deal with Custom Elements is really not too different from dealing with any other node.

    The presented solution is usable with script, style, or even images, all things that might prematurely load content right away, so feel free to reuse the technique.


    ## 6. Confusion between props and attributes

    Yes, this might be annoying. I have created a list of [handy custom elements patterns](https://gist.github.com/WebReflection/ec9f6687842aa385477c4afca625bbf4), and admittedly it's repetitive and boring to deal with this dual attributes nature.

    Truth to be told, the platform gave us, after us asking, a place to pass down props automatically reflected as attributes, and is the `data-` attribute.

    'cause if you fallback accessors to `get/setAttribute` calls, you are better off dealing with `dataset`.

    ```js
    class MyThing extends HTMLElement {
    static get observedAttributes() {
    return ['data-foo', 'data-bar', 'data-baz'];
    }

    attributeChangedCallback(name, oldValue, newValue) {
    name = name.slice(5);
    if (name === 'foo') {
    // ...
    }
    if (name === 'bar') {
    // ...
    }
    if (name === 'baz') {
    // ...
    }
    }
    }

    ```

    That's it, any relevant `dataset` operation will be reflected on the node: `this.datased.foo = "bar"`, not a big deal.

    Despite this solution, wouldn't a decorator also be a valid way to remove unnecessary bloat? If you transpile, transpiling also something in stage 2 shouldn't be too scary (but yeah, no idea what's going on with *that* proposal).

    ```js
    @observedAttributesAccessor
    class MyThing extends HTMLElement {
    static get observedAttributes() {
    return ['foo', 'bar', 'baz'];
    }
    }
    ```


    ## 7. Leaky design

    I agree the `*Callback` method convention is super ugly, and it doesn't work as a guard for the method.

    However, I've been using [attributechanged](https://github.com/WebReflection/attributechanged#readme) utility to have `attributechanged` event instead, but it doesn't look like developers were really looking for that ... also 'cause a manual dispatch is side-effects prone as much as invoking the method directly?

    I don't know, but you like events more, like I do, I can suggest also to have a look at [disconnected](https://github.com/WebReflection/disconnected#readme), which brings `onconnected` and `ondisconnected` events to any DOM element, including Custom Elements.

    These two are part of the core of [hyperHTML](https://github.com/WebReflection/hyperHTML), and [lighterhtml-plus](https://www.npmjs.com/package/lighterhtml-plus), while at least for boolean values, [HyperHTMLElement](https://github.com/WebReflection/hyperHTML-Element) offers a `observedBooleans` extra getter.

    Last, but not least, [🔥 heresy 🔥](https://github.com/WebReflection/hyperHTML) backes almost the best of all these libraries, providing events out of the box, and some other utility borrowed here and there.


    ## 8. The DOM is bad

    I might be too old here, but I think the DOM these days is surely styll not immediate to grasp, but awesome enough to support the explosion of libraries, utilities, and frameworks on top of it, which are all different, and mostly blazing fast, despite all those indirections/

    Classifying the DOM as categorically _bad_ doesn't really seem fair.

    What I think is also unfair, are developers not much into Web Components or even Custom Elements, that keep talking about Web Components as an "_all-or-nothing_" thing, without analyzing the potentials of every single specification of the group.

    Back to the `<Adder a={1} b={2}/>` example, this is how you'd do it on _heresy_:

    ```js
    import {define, render, html} from '//unpkg.com/heresy?module';

    // the Adder components
    const Adder = {
    extends: 'div',
    oninput() {
    const [a, b] = this.children;
    this.dataset.a = a.value;
    this.dataset.b = b.value;
    this.render();
    },
    render() {
    const {a, b} = this.dataset;
    this.html`
    <input type="number" value=${a} oninput=${this}>
    <input type="number" value=${b} oninput=${this}>
    <p>${a} + ${b} = ${parseFloat(a) + parseFloat(b)}</p>
    `;
    }
    };

    // defined globally, instead of locally
    define('Adder', Adder);

    // and rendered on the body
    render(document.body, html`<Adder data-a=${1} data-b=${2} />`);
    ```

    And you can see the result [live in Code Pen](https://codepen.io/WebReflection/pen/WqRywr?editors=0010).

    It might be not as magic as in Svelte, but it needs zero tooling and it works [SSR](https://github.com/WebReflection/heresy-ssr/) too.


    ## 9. Global namespace

    Sure comparing yet another library wasn't the point here, but all my tiny helpers do is to enhance everything already possible via the current DOM, including local custom elements per component: it's possible!

    Indeed I also find the global namespace annoying, but heresy is able to cover that bit as well.

    ```js
    const Body = {
    extends: 'body',
    includes: {Adder},
    render() {
    this.html`<Adder data-a=${1} data-b=${2} />`;
    }
    };

    // note: no Adder definition here, it's kept local in Body
    // and Body can be used locally too elsewhere, no clashes ever
    define('Body', Body);
    render(document.documentElement, html`<Body />`);
    ```

    ## 10. These are all solved problems

    This is were we indeed agree, but for a different conclusion:

    * Custom Elements are already usable everywhere
    * Custom Elements builtin exist natively, and are nicely supported by the right polyfills
    * you don't need the complex parts of Web Components if you just need some custom element
    * you don't need to simulate 1:1 JSX, but you can get pretty closer already with _herey_, _hyperHTML_, or plain _lighterhtml_, which are ale developed via standards, in JavaScript, and need zero toolchain, hence their components are widely distributable in the wild, or surely never too heavy for your own project.

    Please give Custom Elements a better chance, they don't deserve to be put in shame due other parts of the specs.

    THanks for reading.