[HN Gopher] ZjsComponent: A Pragmatic Approach to Reusable UI Fr...
___________________________________________________________________
ZjsComponent: A Pragmatic Approach to Reusable UI Fragments for Web
Development
Author : lelanthran
Score : 59 points
Date : 2025-06-16 15:07 UTC (7 hours ago)
(HTM) web link (arxiv.org)
(TXT) w3m dump (arxiv.org)
| lelanthran wrote:
| Shameless plug; I'm the author. Criticism welcome.
|
| I use this for client-side includes and web components.
|
| No build process, no web-packer, no framework, no npm
| requirement. Just include the JS in your HTML and then you can
| create and include components.
| ramesh31 wrote:
| >No build process, no web-packer, no framework, no npm
| requirement. Just include the JS in your HTML and then you can
| create and include components.
|
| How does the rest of your codebase look?
|
| This is the primary problem with web components. No frameworks
| sounds nice in theory, but it only solves about 30% of the
| problem. The rest ends up an ad-hoc mixture of libraries and
| custom code for state management, routing, styling, cross-
| component communication, etc, to the point that you end up
| building your own framework that is brittle and unmaintainable.
| Applications like this generally end up as a huge confusing web
| of global event buses or with multiple tightly coupled layers
| of prop drilling because of that.
|
| There was a dream that was web components once upon a time. It
| felt like the future. But the APIs ended up half implemented
| (poorly), and the spec was more or less abandoned by everyone
| but Google. Browser vendors could have done things right, and
| focused on pulling in the good things from the framework world
| (i.e. what happened with jQuery), but they didn't.
| spankalee wrote:
| > the spec was more or less abandoned by everyone but Google
|
| This is very, very much not true.
|
| All browsers are very up-to-date with web components APIs,
| and Safari is leading in some areas like scoped custom
| element registries, which they're about to ship first.
| bythreads wrote:
| Disagree, done several custom frameworks for highly regulated
| areas and high load userbases - and as long as you keep to
| seperation of concerns it is a lot more nimble and long term
| viable - easy to wield that 200000 dependencies just to set a
| history state
| WorldMaker wrote:
| I think Google has done a great job of making Web Components
| seem both poorly implemented _and_ way too complex. If
| Angular is the "Google blessed" way of writing Web
| Components and Angular makes a terrible hash of it, who can
| build good Web Components?
|
| Angular and a couple other well known frameworks were
| targeting for far too long pre-spec Google-specific versions
| of Web Components and Web Components moved quickly past that
| and settled into cross-vendor specs with smarter defaults and
| simpler APIs a lot of the marketing damage was already done
| that Web Components were too complex and too poorly
| supported.
|
| So much of the Web Components world is stuck with the
| quagmire of the Shadow DOM, and while there are _some_
| generalized use cases for the Shadow DOM, I have the harsh
| opinion that the Shadow DOM was mostly invented to be
| "better IFRAMES for Ad Publishers" and not much else. I don't
| think enough web developers yet realize that the Shadow DOM
| is entirely optional and its complexity is so much easier to
| ignore and toss than to try to utilize.
|
| > focused on pulling in the good things from the framework
| world (i.e. what happened with jQuery), but they didn't.
|
| I'm coming to the growing opinion that between Web Components
| and the TEMPLATE tag Browser vendors have finally caught up
| with some of the best ideas of the Knockout-era "Progressive
| Enhancement" world, _assuming_ you ignore the Shadow DOM as
| mostly YAGNI.
|
| Sure, a lot of cross-component communication and some of
| state management goes back to DOM APIs and DOM event
| management, but there used to be a lot of knowledge in those
| areas and maybe it past time to return to Vanilla JS ideas
| about some of that. In the time since jQuery and Knockout,
| all browsers today have much more consistent DOM APIs for
| event management, at least.
|
| (Similar for routing. Vanilla routing, even "SPA" routing is
| easier than ever with modern APIs, even the API not fully
| standardized and cross-browser yet, but also the improved
| APIs for hash navigation. Also, Web Components seem a great
| reminder that MPA routing is great and brilliant, and so well
| tested in browsers and servers. With View Transitions now
| generally well supported, and getting better, many MPAs feel
| as good or better than SPAs even.)
|
| (And I feel like most styling problems with Web Components
| are self-inflicted with and by the Shadow DOM. It's nice to
| embrace the cascade again, if you can.)
|
| I was bullish on Web Components for a while, but most of my
| complaints have disappeared in recent months, and especially
| in realizing that I was very happy ignoring everything about
| the Shadow DOM. Sure, I'm not using Web Components without a
| "framework" but I'm using a far smaller "view engine" than a
| React or Angular, a lot more "Vanilla", and feeling a bit
| like it's a Revenge of Knockout sort of era.
| lelanthran wrote:
| > Sure, a lot of cross-component communication and some of
| state management goes back to DOM APIs and DOM event
| management, but there used to be a lot of knowledge in
| those areas and maybe it past time to return to Vanilla JS
| ideas about some of that.
|
| My approach is, actually, an attempt to inject some Vanilla
| into front-end component development.
| WorldMaker wrote:
| I think many of us, as this linked article that kicked
| off this discussion included, are thinking of various
| ways of using more Vanilla approaches. I appreciate the
| above poster's complaints that we aren't in some promised
| land of being able to do things 100% Vanilla without some
| form of reactivity management. That's still all in
| progress, no matter where you are in the Observables
| versus Signals "debate", Browsers are back to showing
| interest in native specs for one or both. (I personally
| think Signals are just "worse, poorly encapsulated
| Observables", but either proposal is a good building
| block for whatever the next steps are and thinner
| libraries to build on top of them will be.) But Web
| Components are mostly some steps in the right direction,
| I think, while that other work remains ongoing.
|
| I also like gradual typing too much to expect to be 100%
| Vanilla any time soon. Typescript is too handy a
| verification/testing tool and while I'm still watching
| the native type stripping proposal with TC-39 with a lot
| of interest, it's certainly not on a fast track.
| spankalee wrote:
| Angular has nothing to do with web components. It isn't
| even a way to write web components.
|
| If anything is the "Google blessed" way of writing web
| components (Google doesn't really work that way), it's Lit:
| https://lit.dev/
| WorldMaker wrote:
| I'm aware of Lit and thought about mentioning some of its
| past versions too from the pre-spec era, but I think
| those are even more forgotten.
|
| Around Angular 8-14 era Angular had a lot of "Angular is
| Web Components" marketing and assured devs at the time
| that the Angular way including CSS Modules support and
| _its_ HTML Template language (and its super complex
| compiler) were "browser standards and the future of Web
| Components". Obviously none of that played out, CSS
| Modules are still in spec debate, the TEMPLATE tag was
| much simplified and no "template language" has been
| knighted as "the template language". But it was all so
| heavily marketed and it left scars in what people think
| of when they think of Web Components. People still expect
| CSS Modules. People still expect some sort of "blessed"
| template language out of the box for "Vanilla
| templating". Among other curious decisions by people
| marketing Angular to developers as a way to prepare for
| Web Components. (We can talk for hours about everything
| wrong with Zone.js and why it has taken Angular to
| version 20 to start to undo a lot of that [brain]damage.)
|
| Lit was never quite so extreme in its worst pre-spec
| days, and it is useful for its templating language looked
| different enough from Angular's to, even at the time,
| prove that Angular's template language was neither HTML
| nor necessarily the template language to be knighted by
| Web Components. But it still had some versions with
| questionable Google-only decisions that are best
| forgotten today, and apparently easily forgotten today.
|
| Of course, you don't have to take my anecdata on it, the
| sources still exist. If only Google made a search engine
| that works in 2025 maybe you could even find them.
| stillpointlab wrote:
| I haven't had too much trouble with Shadow DOM so far, and
| I was especially surprised to learn about `<template
| shadowrootmode="open">` recently. It makes SSR rendering of
| web components with shadow DOMs viable and appears to be
| well supported in browsers.
| lelanthran wrote:
| > How does the rest of your codebase look?
|
| Quit neat, compared to the React/Redux things I've maintained
| in the recent past.
|
| > No frameworks sounds nice in theory, but it only solves
| about 30% of the problem.
|
| "No framework" is not meant to be a prescription, it is an
| indication of the dependencies.
|
| IOW, I mean to say _" No framework required"_, I did not mean
| to say _" Don't use a framework with zjs-component"_.
|
| > the _[web component]_ spec was more or less abandoned by
| everyone but Google.
|
| Are you being sarcastic, maybe?
| fayten wrote:
| I always love seeing more done in the web component space. I
| think Lit has the no build process captured pretty well and
| they include things such as a router.
|
| I do prefer the style of of your components more, where you
| separate out the script and styles with html tags. I don't know
| if one way or the other is superior for performance, I but just
| like the separation verse the templated strings in Lit.
|
| With build tools being so straightforward now-a-days, I
| struggle to see the value in the build less approach. One use
| case I can think of is maybe a constrained environment where
| the application contains some kind of customizable user
| components fully in the browser like a reporting WYSIWIG of
| some kind.
|
| Is there a particular reason you prefer this approach?
| cosmic_cheese wrote:
| With the caveat that I'm generally outside of the web dev
| sphere aside from casual tinkering: no build process means no
| setup and one fewer thing that can break. That's valuable in
| itself.
| lelanthran wrote:
| > Is there a particular reason you prefer this approach?
|
| Compared to Lit? Firstly, I _like_ Lit. My approach is better
| _for me_ because there are far fewer things to know in order
| to create a reusable object and there are far fewer things to
| know in order to use an existing object.
|
| IOW, my approach trades off functionality in favour of a
| lower cognitive burden _for me._ I just wanted something that
| had the minimum functionality I need - create an object and
| then reuse it. For me, anything outside of that goal is
| peripheral burden that I 'd rather not get bogged down in.
|
| I agree with many here that this is not an approach _for
| them_ , maybe even _for most_ , but I am certain that if I
| find something useful that increases my velocity of feature
| delivery, then maybe someone else will as well.
| dfabulich wrote:
| Zjs is a web component for doing client-side includes. The Zjs
| code itself is itself a web component that extends HTMLElement
| and registers itself as <zjs-component>. It's only 100 lines
| long. In its connectedCallback, it fetches the URL of the
| "remote-src" attribute, and injects its content in innerHTML.
|
| Client-side includes are bad. The industry avoids them, for
| good reasons.
|
| First, they hurt performance. The client can't start
| downloading a zjs-component content until its connectedCallback
| runs. If a zjs-component includes another zjs-component, the
| client can't start downloading the nested component until its
| parent component downloads and executes. If your components are
| nested at N layers, this means that the page won't finish
| loading until N serial non-parallelizable requests succeed. On
| cellular networks, where network latency can be measured in
| seconds, if you have four layers of components, you're looking
| at adding 10+ seconds to page load.
|
| Second, each client-side include will cause a layout shift, as
| the <zjs-component> element starts out at 0px tall, and then
| will change in height as the component loads. This is bad.
| https://web.dev/articles/cls
|
| Finally, in your article, you claim that reactivity is "out of
| scope for a _component creation_ mechanism, " but there is no
| universally recognized "scope" for component creation. You'd
| need to justify the claim that reactivity is out of scope.
|
| If you think reactivity matters at all, then you'd need to
| demonstrate how to use client-side includes in the context of a
| framework that does provide reactivity.
|
| HTMX is a lightweight framework that provides a reactivity
| framework around client-side includes. https://htmx.org/ You
| might especially appreciate the academic theoretical framework
| the HTMX team provides in their book, Hypermedia Systems.
| https://hypermedia.systems/
|
| HTMX is pretty good for what it does; it's not clear that
| anyone should prefer ZJS over HTMX for anything. But it's also
| not clear that HTMX is better than more frameworky
| alternatives, especially React Server Components.
|
| Dan Abramov has written a series of articles explaining the
| theoretical framework behind RSC. Here's one that's relevant to
| you. https://overreacted.io/one-roundtrip-per-navigation/
| chrisweekly wrote:
| Excellent comment; it's well-informed, accurate, and
| actionable feedback. Agreed 100%.
| bythreads wrote:
| Just use lit, and build to vanilla
| lelanthran wrote:
| That's a lot you wrote, thank you for all that effort and
| time. I will do my best to address them:
|
| > Client-side includes are bad. The industry avoids them, for
| good reasons.
|
| The industry we are talking about does lots of things that
| has caused many to consider "the industry" to be something of
| a running joke.
|
| You may not like client-side includes, but it really is
| something useful to have. Wanting to have client-side
| includes and not wanting to spin up an entire tech stack of 5
| or so different technologies is not unreasonable.
|
| > First, they hurt performance. _[...]_ On cellular networks,
| where network latency can be measured in seconds, if you have
| four layers of components, you 're looking at adding 10+
| seconds to page load.
|
| 1. The first time, sure. It's 10s the first time those 4
| components are downloaded. Any other component using any of
| those 4 components on the rest of that page, or if that page
| is reloaded, will have a 0s download.
|
| 2. On cellular networks I currently get longer wait times
| than that for SPAs used by the mainstream frameworks anyway
| _today_. I 'm not losing any sleep over the pathological
| cases which affect mainstream frameworks and libraries as
| well.
|
| 3. I call it pathological because I feel that it would be an
| extreme case to have lots of components being downloaded, of
| which only a few get reused. The whole point to reusing is so
| that the component only gets downloaded once, even if used in
| multiple places.
|
| > Second, each client-side include will cause a layout shift,
| as the <zjs-component> element starts out at 0px tall, and
| then will change in height as the component loads. This is
| bad. https://web.dev/articles/cls
|
| I agree. It's a trade-off that many sites _currently_ make,
| SPAs included. While I find it incredibly annoying, this
| component is for when that trade-off decision _is already
| made_.
|
| > Finally, in your article, you claim that reactivity is "out
| of scope for a component creation mechanism," but there is no
| universally recognized "scope" for component creation. You'd
| need to justify the claim that reactivity is out of scope.
|
| I'm a bit confused about this; if there is no universally
| recognised "scope" for creation of an object in an OO
| environment, why would I have to first define what scope is
| and then defend that decision? Most (all?) mainstream OO
| approaches don't have reactivity within scope for the
| definition of an object, so I feel that any claim that
| reactivity is within scope for this specific OO approach
| needs to provide some sort of reason why that an exception
| must be made for zjs-component so that it is measured against
| a higher bar than other OO approaches.
|
| > HTMX is a lightweight framework that provides a reactivity
| framework around client-side includes. https://htmx.org/ You
| might especially appreciate the academic theoretical
| framework the HTMX team provides in their book, Hypermedia
| Systems. https://hypermedia.systems/
|
| I've read those.
|
| Regardless, if you are building an SPA with Facebook level
| number of components, then this is not for you. IOW, this may
| not suit your use-case, or even most of your use-cases. I
| find it suitable to an embarrassingly large number of use-
| cases, though.
|
| I build Line-of-Business applications for internal use at
| companies. Even the most complex UI in these LoB applications
| have only a few different components, and at most two levels
| of nesting (these component objects are not like React
| components at all - they're meant to be instanced inline in
| HTML, which is both a drawback and an advantage).
| spankalee wrote:
| I'm guess that since this is an academic paper and not say, a
| website or GitHub repo, that you're in school. But given the
| research paper nature of this, did you want to contrast and
| compare to other methods of authoring web components?
|
| There are many existing and popular approaches out there. Is
| your take easier, faster, or more capable? That discussion
| would be interesting.
|
| Two that I help maintain are Lit (https://lit.dev) and Heximal
| (https://heximal.dev/). Of those, Heximal might share the most
| with Zjs.
| dleeftink wrote:
| Also Facet.js! Declarative to a fault.
|
| [0]: https://github.com/kgscialdone/facet
| lelanthran wrote:
| > I'm guess that since this is an academic paper and not say,
| a website or GitHub repo,
|
| It is a github repo. And a website too, IIRC. And now,
| finally, it is a paper as well.
|
| I haven't been evangelising this as I have no burning desire
| for popularity. I posted the link here for discussion and
| criticism.
|
| > that you're in school.
|
| I wish. I've been professionally developing (i.e. getting
| paid for it) for close on to 30 years now (I am almost 50).
|
| I like Lit, but was not aware of heximal. Will check it out.
| ilarum1 wrote:
| This is cool. Remindes me of simplicity of https://tg.pl/drab
| which need phoenix/elixir.
| willmeyers wrote:
| For anyone curious, the source code:
| https://github.com/lelanthran/ZjsComponent/
| hirako2000 wrote:
| I came across Yoffee, also requires no specific build system or
| dependencies. Proposes to either code native web components, or
| not. No web components means instances are used to get fragments,
| and still support a state store. Not only one state store can be
| passed over to instance, as many as we want.
|
| Can you compare with ZjsComponent?
|
| Pure html and JavaScript from my experience is a relief, I still
| stuff the trauma of seeing jsx error cluttering the console with
| barely anything useful to troubleshoot.
|
| How doe ZjsComponent compare, any advantage with your paradigm?
| sandreas wrote:
| I like vanilla components... Personally I think that instead of
| providing either frameworks or vanilla compnents, frameworks
| should provide a way to compile components to independant vanilla
| JS (similar to svelte not needing a "runtime").
|
| This way it would not matter this much how you deploy components
| and this compiling step could probably have its own API with
| hooks and callbacks.
| notnullorvoid wrote:
| Older Svelte versions may not have needed a runtime, but Svelte
| 5 definitely does.
|
| Runtimes are good, the abilities of web components suck
| compared to most framework runtimes.
| mosdl wrote:
| Seems to be taking how old frameworks used to work in the old
| days (download some html/js and run in an closure) and wraps it
| into webcomponents. Neat, but not sure why its a paper.
| coneonthefloor wrote:
| Yea, I feel like we are coming full circle with frontend
| JavaScript. To me this seems like a concept that has been
| around a while, but it's being presented as a novel idea. I'm
| also baffled as to why it's a paper.
| lelanthran wrote:
| > Neat, but not sure why its a paper.
|
| I have a very good reason for that[1]. I will, however, concede
| that this approach might have been used somewhere public in the
| past, even though I have no knowledge of seeing this approach
| previously.
|
| A poster downthread mentioned a link that I am going to read up
| when I have time, that seems like it is the same approach as
| zjs-component.
|
| -----------------------------------
|
| [1] Not _" done on a bet"_, but pretty similar.
| SoKamil wrote:
| Okay, but what is the reason? I didn't understand it from
| your comment.
| croemer wrote:
| He has maybe mentioned to someone that he'll write a paper
| on this topic
| lelanthran wrote:
| As I said elsewhere:
|
| > Posting on Arxiv is a great way to signal that you don't
| intend to monetise something, aren't pretending to be an
| influencer and not posing as some thought leader.
|
| In short, I'm not trying to build a community, I'm not
| trying to get followers, I'm not trying to build an email
| list.
|
| I want to publish something to the world, but I'm not going
| to run the gauntlet of peer review publishing.
|
| Arxiv aligns with my goal for this.
| amingilani wrote:
| Hate to be the one to pull a dang, but, remember:
|
| > Be kind. Don't be snarky. Converse curiously; don't cross-
| examine. Edit out swipes.
|
| -- https://news.ycombinator.com/newsguidelines.html
| krystofee wrote:
| Is there some clean way to pass components or just html to
| components using this framework without having them in strings?
| This is issue I see with most of these approaches.
| lelanthran wrote:
| > Is there some clean way to pass components or just html to
| components using this framework without having them in strings?
|
| No, there isn't. Parameters are passed in as plain strings.
|
| > This is issue I see with most of these approaches.
|
| I didn't need to solve 100% of the problem, getting the most
| common 90% is sufficient.
| lacoolj wrote:
| This kinda reminds me of a slimmed down version of Polymer.
|
| I like the simplicity, and it might have potential to stack upon
| itself to provide the other missing elements like reactivity,
| etc.
|
| Keep up the good work
| pointlessone wrote:
| It's remarkable that you can write a paper about a 100 lines of
| code (literally). Maybe I should try that some time.
| bsingerzero wrote:
| One of John Nash's most famous paper's is 1 page:
| https://www.pnas.org/doi/abs/10.1073/pnas.36.1.48
|
| Large systems is not a requirement for novelty.
___________________________________________________________________
(page generated 2025-06-16 23:00 UTC)