by lelanthran | 2025-06-17 13:03:46+00:00
> The point is if HTML inclusion is not the main feature, but rather the per-instance state then regular WebComponents seem like a better solution if only for being a standard.

Yes, they are better, but they also require more lines of code to express the same component; I consider zjs-component more as a low-code alternative to extending HTMLElement than as a replacement for HTMLElement.

For example, extending HTMLElement into a `<my-header>` element and a `<my-footer>` element is much more boilerplate than simply writing the header and footer fragments into an HTML file and doing `<zjs-component remote-src-'...'>` for `header.zjsc` and `footer.zjsc`. No class definition, no component registration, no shadow DOM/light DOM distinction.

At this point it is nothing more than a fancy include/import library.

Now once you have that, maybe for some of those remote sources you want some code to execute (headers for example may want to make an additional request to determine how many notification counts to display).

You can, in the header.zjsc file, export a constructor function. No boilerplate, no `class` keyword, no element registration, etc.

Maybe you need a `check for new notifications` button in the header at some later stage, then you can export a function `updateNotifications()` in header.zjsc, add a button somewhere in that file, and set the attribute `onclick="ZjsCompontent.send(this, 'updateNotifications')`.

So, sure, you can do all this with a little bit of boilerplate using standard web components, but I got tired of writing what is essentially 90% the same code for fairly trivial components.

I really really wanted client side includes, but I also really really wanted them to be cheap to write, as in "here's some HTML + JS that comprises an object, with exactly zero boilerplate".

With webcomponents I'd use custom events to ensure that any child element can invoke a method in the webcomponent (adding or removing itself from a menu, for example). Creating the custom event is unwieldy in HTML onclick attributes; can be done but is very much mostly boilerplate.

The zjs-component approach is to use the static method to dispatch an instance method name and arguments to that method call directly in the onclick (or other) attributes.

When I use terms like "lightweight" and "heavyweight", I do not mean in terms of runtime bloat/lack of bloat. I mean in amount of boilerplate lines that are repeated for every component that is created.

The last thing I did not like about web components was the potential for clashes. Where you see:

> To me this looks not unlike the primordial div soup.

because it's all the same tag, I see potential clashes because one library might register the same tagname as another, overwriting it. With web components there is no safe way to have two different menu libraries if both of them register the same tagname.

This problem does not exist if the component is written as a zjs-component because, by necessity alone, it is not possible to have two different components at the same `remote-src` path.

So, yeah, "it's all divs" is a valid complaint, but it does fix a potential clashing when using different components from different authors.