by lelanthran | 2025-06-17 22:12:42+00:00
> I see what you mean. I do understand the desire to reduce boilerplate. I'd go for a small framework like Lit (I'm sure there are even smaller ones out there) for that but I wouldn't fault anyone for writing their own. I guess, good for you you could get a paper out of it, too. It just doesn't feel particularly novel to warrant one.

I appreciate the sentiment; while this is, indeed, a paper, it is not a published or peer-reviewed paper. I wrote it with no intention of actually publishing it anywhere, and putting it on Arxiv is better long-term than putting it into Github or similar (I expect Arxiv to outlive any code forge).

In much the same way that I looked at web components and thought "What a nice idea. Here is how I can make this incrementally better and support client-side includes as well", I am hoping that this 100-lines of code will someday be looked at by someone else, who will (with the benefit of future knowledge and tech), then say "What a nice idea. Here is how I can make this incrementally better AND support <some future feature we cannot see right now>".

In any case, I thank you for your criticism and your time; your criticism can only make this better (for example, after reading your criticism, I think that showing a side-by-side comparison of my counter example with a custom element doing the same thing will make it more obvious why I find zjs-components more pleasant to write and use than Custom Elements).

Cheers :-)

[EDIT: Here is the comparison, in case you are still curious]

Here is the small comparison; I gave ChatGPT the ZjsComponent README.md and got it to write the example in the README as a custom element web component.

Here are the two implementations:

Implementation as a zjs-component:

<div> Counter Value: <span name=counter-value>0</span> </div> <div> <button onclick='ZjsComponent.send(this, "increment", 1)'> +1 </button> <button onclick='ZjsComponent.send(this, "increment", 2)'> +2 </button> <button onclick='ZjsComponent.send(this, "increment", 5)'> +5 </button> </div> <script> function increment(amount) { const el = this.querySelector("[name='counter-value']"); el.textContent = parseInt(el.textContent) + amount; } exports.increment = increment; </script>

Usage of zjs-component:

<zjs-component remote-src=counter.zjsc> </zjs-component>

Implementation as a custom element web component:

<!-- counter-component.js --> <script> class CounterComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.innerHTML = ` <div> Counter Value: <span id="counter-value">0</span> </div> <div> <button data-amount="1"> +1 </button> <button data-amount="2"> +2 </button> <button data-amount="5"> +5 </button> </div> `; } connectedCallback() { this.shadowRoot.querySelectorAll('button').forEach(btn => { btn.addEventListener('click', () => { const amount = parseInt(btn.getAttribute('data-amount'), 10); this.increment(amount); }); }); } increment(amount) { const valueEl = this.shadowRoot.getElementById('counter-value'); valueEl.textContent = parseInt(valueEl.textContent, 10) + amount; } } customElements.define('counter-component', CounterComponent); </script>

Usage of the custom element web component:

<counter-component></counter-component>