6 ms·
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 n
by lelanthran 1y ago
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 1y ago>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 1y ago> 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 1y agoDisagree, 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 1y agoI 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 1y ago> 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 1y agoI 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 1y agoWith 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 1y ago> 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.
- 20after4 1y agoOne major benefit of not having a build process is that you can make changes and instantly see the result without delay.
- dfabulich 1y agoZjs 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 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/ https://htmx.org/ You might especially appreciate the academic theoretical framework the HTMX team provides in their book, Hypermedia Systems. https://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/ https://overreacted.io/one-roundtrip-per-navigation/
- chrisweekly 1y agoExcellent comment; it's well-informed, accurate, and actionable feedback. Agreed 100%.
- spankalee 1y agoI'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 https://lit.dev) and Heximal (https://heximal.dev/ https://heximal.dev/). Of those, Heximal might share the most with Zjs.
- dleeftink 1y agoAlso Facet.js! Declarative to a fault. [0]: https://github.com/kgscialdone/facet https://github.com/kgscialdone/facet
- lelanthran 1y ago> 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.
- zackmorris 1y agoThis is great! A few comments/questions if you have time to respond: 1) I thought that React already worked this way until I learned it, and was horrified. Similar disillusionment with Ruby on Rails, Objective-C on iOS and Java on Android. Why someone would want to mix code and markup, rather than define components via code to be used within markup, blows my mind. Said as someone who uses PHP daily and sees JSX as its frontend analog. 2) I appreciate that async/await and promises were deliberately left out of the spec. I view their use as an anti-pattern, since I've programmed both async/nonblocking and sync/blocking sockets logic, and view sync as far superior if deterministic behavior is the goal. I know this is a contentious subject, but IMHO async will someday be considered the goto of the web and be deprecated across most languages. Better approaches such as scatter/gather arrays, coroutines and channels (like in Go) exist to remove the temporal/imperative aspect of logic and make it declarative without requiring red/blue functions. 3) The main problem I've encountered with React is that it's nearly untraceable in web inspector. It's impossible to tell which component object instance is associated with an HTML element. It's hard to tell where attribute values came from, unlike function arguments: are they props that aren't declared in a function prototype? are they magically mapped from redux state? are they derived neither in the constructor nor componentDidMount() or affected by an affect they weren't supposed to be? etc etc etc. Component methods are buried in dozens of anonymous functions and boilerplate. Promise values can't be inspected until their then() method without using tricks like Promise.resolve(), which don't always match intuition. Redux state can't be conveniently inspected without adding debug lines to the source code and/or installing a browser extension. Code gets mutated by the build pipeline so it's hard to find code snippets to set breakpoints. I could go on. Have you found ZjsComponent easier to debug, and if so, how? 4) I applaud your use of caching for client-side includes. IMHO much of the complexity of React is around its deliberate rejection of HTTP idioms and metaphors. We already solved these problems declaratively in the mid 1990s, why are we manually managing initialization and state, even if through Redux? That was a rhetorical question, but really, React doesn't seem nearly as reactive as something like a spreadsheet that just re-renders cells that reference cells that changed. Basically all of its component methods could be replaced by the render() method containing a JSX template, with the state boilerplate handled by the framework internally via declarative and data-driven techniques like observing variables for changes. Instead, they put the onus on developers, which wastes all of our time and sanity. 5) Do advanced use cases such as components built with other components, subresource integrity (SRI) and observing variables similarly to Vue.js watchers "just work"? I'd be curious to hear your vision for the future. 6) (Special mention) after driving myself crazy manually managing recycler views in iOS, Android and React, I wanted to highlight https://github.com/splinesoft/SSDataSources https://github.com/splinesoft/SSDataSources and https://github.com/SDWebImage/SDWebImage https://github.com/SDWebImage/SDWebImage (no affiliation with either). The idea is to populate callbacks to handle the lifecycle of table view cells. That way, an array or generator in memory can be mapped to a table and automagically handle all scrolling and resizing edge cases. Including dynamically loading images and other async data with caching via SDWebImage, without crashing when navigating between view controllers that get disposed, while running as fast as possible. With these metaphors, all other GUI elements can be derived. These are the only frameworks that I've ever used that do all of this correctly. Which let me do declarative web-style programming natively by treating tables as already fully populated, rather than building rows and columns programmatically. Perhaps something in this could inspire a ZjsComponent that "just works" like an ordinary web table, but fast, without the memory hogging of the browser DOM or React's virtual DOM.