Hacker News new | past | comments | ask | show | jobs | submit login
Web components will outlive JavaScript frameworks (jakelazaroff.com)
310 points by cdme 6 months ago | hide | past | favorite | 244 comments



just because htmx (which is a library, not a framework) was mentioned, I'm going to respond to some stuff in the article

first and foremost, the article doesn't talk about synchronizing state w/a server, which is what htmx is focuses on (via hypermedia exchanges), so htmx is orthogonal to WebComponents in this regard

> There’s a cost to using dependencies. New versions are released, APIs change, and it takes time and effort to make sure your own code remains compatible with them.

This is why htmx is dependency-free and focuses intensely on backwards compatibility (e.g. it is IE11 compatible). intercooler.js, which was htmx 1.0 and has one dependency, jQuery, was released in 2013 and is still supported. A lot of other javascript libraries have a culture of API rewrites and difficult upgrades, but htmx is explicitly not like that and shouldn't be heaped into that general culture. In htmx 2.0, our only breaking change is likely to be dropping IE support.

Will web components outlive htmx? Well, they are part of the browser, so presumably yes. But, insofar as I can help it, htmx should be very stable and churn free going forward. The API is basically correct (yes, w/ a few warts and mistakes) and I see no need to rewrite everything for the sake of purity or sexiness.

And, most importantly, htmx answers a different question than Web Components: how should I synchronize state w/ the server.


We're replacing React with Htmx at work (about a year into it) and have found WebComponents to be very useful to re-use some of the React components that we want to preserve and treat a bit like using native browser widgets (input, select, textarea). Specifically, a WebComponent lets you hook into the lifecycle of a DOM element that is being modified by the outside world (morphdom via Htmx). In the event of attributes changing, you want to tell the React component about that. And in the event of the node being removed from the DOM, you want to tell React to run its cleanup procedures. I think that we weren't able to do this in a clean, efficient way without WebComponents.

The end result is that we can stick to Htmx's way of doing things, i.e. keeping all business logic state on the server, and only a few conservative things are client-side (such as currently focused element, text being typed in an input, things like that). Every step we take towards this, it offers a much better user experience with fewer bugs and race conditions, so it's worth the effort.


that's great to hear and confirms my intuition that web components and htmx would go very well together


what about alpine.js, seems great to me and more natural(not mixing html and js behind the scene like some black magic)

both are really for SSR applications, a modern jQuery to some extent. For CSR(client side rendering), you still have to use react/vue/mithril/etc


Author here — I’ll remove that sentence since it looks like it’s being received in a way I didn’t intend. Sorry about that! I actually mentioned on Twitter [1] that web components are a natural fit for hypermedia-friendly scripting as described in your essay [2] (which I like a lot).

[1] https://x.com/jlazaroff/status/1717176726248108469

[2] https://htmx.org/essays/hypermedia-friendly-scripting/


Well, I think that the article (and sentence) is correctly pointing out an issue w/many JS frameworks, I just don't think it applies to htmx necessarily. I don't mind you keeping it up and having a debate around the topic: in as much as htmx does cause upgrade pain that's a burden of using it that deserves to be called out.

I don't think you need to change the article, I just want to give my perspective as the author of htmx. It isn't realistic to expect everyone to write perfectly precise articles at all times, especially when the htmx reference in the article isn't a focus (likely included just because you kinda like htmx :)


I kind of hoped the long term result of htmx, instead of just being a Javascript library, was to become a standard in a newer version of HTML itself. The constraints of only forms being able to do POSTs, and the only way to handle the response is to rewrite the entire page seems arbitrarily limiting. If htmx were just HTML6 or whatever, it'd outlive all the Javascript frameworks.


I think this is still possible.

It took a decade for JQuery to be nearly completely absorbed by browser standards.


For the most part, jQuery was absorbed into ES/JavaScript, not HTML.


The most visible part of jQuery for me was always querying selectors - $('.some > a.selector'); and that certainly was something integrated into HTML/the DOM as document.querySelectorAll('.some > a.selector').


Well yeah, that's still under "browser standards."


The difference is that the internet can exist (and did) quite well without JavaScript. Without HTML there is no internet. Furthermore, ECMAScript is a language and W3C/WHATWG are a consortium that maintain HTML.


Sorry to nitpick, but there is a lot more to the internet than the web.


And the browser APIs still have significantly worse ergonomics than jQuery


You'd have to merge JavaScript and HTML to get htmx in any usage capacity. HTML is not a programming language, it's a markup language.


I have thrown together a minimalist extension to HTML that I think captures the core ideas of htmx, although you are right that there are still some outstanding issues that probably need additional thinking to make it widely useful:

https://gist.github.com/1cg/d1ad1ddd5f43a8a993cd9f711135edc9

Here is an example button using these proposed extensions to HTML

  <button href="/example"
        method="patch"
        target="#divToReplace"
        onClick="this.submit()">
    This is an example button hypermedia control
  </button>


I'd vote for being able to put an href attribute on any element (eg <div href=""> and <span href="">), and maybe binning <a> entirely. That seems like such an obvious enhancement to me, I figure there's probably a deep reason it hasn't been done.


Not sure of why it was done then, but currently for accessibility a link says, "This takes you to another page / URL" while a button says, "This performs some action / triggers some event."

If everything and anything is clickable, how does technology that supports accessibility handle that? Note: This isn't a way-a-figure-you-fool question. Not at all. It's a sincere question in the sense that accessibility matters, we can't forget that. So if we change, how can we be certain accessibility isn't left behind?


Yeah, I wondered if it was accessibility, or maybe a limitation to support text browsers.

To take the opposite view, there's not much we can't wrap in an <a> since HTML5 (eg <a href=""><div></div></a> is valid, and makes the div clickable). How do accessible browsers support that today?


So you want to inline JavaScript, similar to CSS and the `style` attribute?


I would prefer something more like what htmx has in hx-trigger:

https://htmx.org/attributes/hx-trigger/

w/ an explicit and declarative syntax, but that attribute is fairly involved

this was a brief exercise in thinking about the minimal changes necessary to HTML to support something like htmx, and unfortunately there isn't any attribute that maps to hx-trigger in the same way there is for other htmx attributes, so I resorted to the on* attributes + generalizing the submit() function on forms.


Yes and no. You wouldn't call a <form> inlining JS while it does come with some degree of interaction. It would be an expansion of HTML to include a few new things to (ideally) enable a wider rage of lightly-interactive websites to be HTML only.


according to the people who write standards, but not the people who write browsers


I literally just started with htmx, but can’t you override both of those behaviors? hx-<http verb> on the form will switch the verb it uses, and you can swap outerhtml, innerhtml, or some other css target?

Or am I incorrect?


I think you've slightly misread - they specified only forms can do POSTs, not that forms can do only POSTs. (Also, they're talking about vanilla HTML, not HTMX).


Oh I did not catch that … oops


> The constraints of only forms being able to do POSTs

HTML elements shouldn't do POSTs, that's why JavaScript exists. <form> and <a> are elements that do HTTP requests but the same can be added to any other html or custom element. html integration with JS doesn't need another layer.


> But, insofar as I can help it, htmx should be very stable and churn free going forward. The API is basically correct (yes, w/ a few warts and mistakes) and I see no need to rewrite everything for the sake of purity or sexiness.

This is awesome to hear. I've been eyeing htmx a bit lately for some pet projects, but as a primarily backend-focused engineer, most JS libraries I import tend to be a large maintenance burden moving forward, with major API changes happening regularly.

I'll definitely take htmx out for a spin.


I have been using HTMX a lot and would highly recommend it as a backend engineer.

Historically I have constantly had an issue following JS frameworks and more importantly their build processes. Too much mental overhead when the majority of things I am building don't really benefit from a SPA style. I started my journey using Backbone.js a decade ago and enjoyed the relatively simple apis. Everything that came after for me has been a nightmare. Finally with HTMX I am in the groove and able to easily build what I want in a pattern that I enjoy.


I've been wanting to rewrite a side project SPA using htmx. I've never been that interested in Web Components, but it is an intriguing idea to use with htmx. It'd certainly make generating the HTML fragments server-side less complex to template.

On a side note about htmx. Really compelling concept, I wish there was a larger community around it. Chicken and the egg kind of a problem, but there just aren't a lot of resources (blog posts, videos, etc) compared to many other web frameworks. Basic stuff like how do integrate something like Auth0 auth into an htmx app.


There is no "htmx app". You'd search for how to include auth0 in, say, a django app.


It seems like examples are usually oriented around specific popular SPA frameworks (e.g. React) or focused on an existing server side rendered app that you are adding interactivity into. I understand extending server-side way. The kind of stuff I used to do with jQuery back in the day adding interactivity into otherwise SSR pages.

In a world of either SPAs or SSRs, htmx straddles the two. That is what makes it so interesting and unique, but it is also a different enough model to not always cleanly map from my pre-existing skills/patterns.

For the app I'm doing, I'd really prefer to keep it an SPA. In that the URL never changes, and there is never a full page reload (outside of OIDC/sign-in). I'm sure I can get there, I just need to think about the architecture a bit.

I'm kind of obsessive in this app about loading the app being nearly instant (I personally use it countless times a day). I really love the idea of returning back a full rendered page of HTML that wouldn't require any other API calls before showing the content.

The current stack (which I hate, but it works, I wrote it, and so who am I going to blame?) - is PHP/MySQL. My concept for something that will be lower maintenance going forward (keeping up on PHP versions...ugh.) is to use Deno + oak + SQLite (running in Deno using WASM) on the server to render HTML fragments/pages, and htmx on the front end. With no build step and no database server to maintain.


The community is relatively large but I understand what you are saying.

I think really all you need to do is start using it. The HTMX api is minimal but powerful. At the end of the day you are requesting chunks of html that replace existing sections in your html.

You are building an HTML driven app so your auth workflow is going to be whatever HTML can handle.


If your SPA is written in Typescript, you're going to throw away a lot of safety checks moving to htmx.


A move from SPA means business logic moves to the backend and becomes hypermedia-driven, so the correct comparison if you want to think about type safety is if the backend server is type-safe. htmx is mostly declarative and its correct use could be statically checked with basic tools--it's not meant to contain complex logic.


Isn't IE dropped in the upcoming htmx 2.0 release? Not that it's a bad thing, but goes against the superior backwards compatibility claim.


"In htmx 2.0, our only breaking change is likely to be dropping IE support." from a comment by the engineer who writes and maintains htmx.


I wrote all of non.io with vanilla webcomponents - it's a full SPA built on them. A few learnings I'll share with going beyond just a simple nested blog component:

State management is still unanswered. You'll end up having to do a lot of this yourself if you aren't using a wrapper framework. One nice thing about React is state management is mostly solved and there are existing patterns for it. There's expectations of how it's done. With web components it's the wild west, and since you can't pass complex objects as attributes like you can in jsx, you end up doing a mix of attributes, events, and calling class functions directly.

Performance isn't as big of a win as I'd have hoped. I actually reverted some smaller atomic elements (i.e. icons) away from being web components as their instantiation cost wasn't worth it when I had hundreds of these elements on the page. Static elements, despite the readability they provide in code (i.e. <nonio-icon glyph="hamburger">), just aren't worth using web components for, which was fairly disappointing.

That said, there are things I REALLY enjoy about web components. As the author shared, it's incredibly easy to add a component to new pages, regardless of the framework being used. If something is built using web components, you can truly use it anywhere. This has been really nice when building supporting sites like api docs for nonio, where I can easily pick and choose what components I want despite having a different stack. Need to embed a <nonio-user> component? Import the js, add the html, you're golden.

Style encapsulation of shadowroots is quite nice. I really love not having to worry about breaking styling of any component as I work on a page. It means less guesses and checks of clobbering styling of other elements, and less of a need for a visual diff framework to ensure this hasn't happened.

The other aspect I enjoy is how slim the package sizes are. No libraries or anything extra to load, everything is baked in. Because you can pick and choose components you need so easily as well, it's incredibly easy to keep package sizes down.

If anyone is curious, source components for nonio are here: https://github.com/jjcm/nonio-frontend/tree/master/component...


Regarding the point you mentioned about not being able to pass objects via attributes, you can however pass them via properties on the element.

Also as for the state management side of things there is nothing at all stopping you from hooking up whatever state management solution you want. I’ve even seen a bunch of solutions that use the browsers built in event model as well if keeping dependencies to a minimum is your goal.

Finally, the last thing I would suggest is that writing an entire app in vanilla web components is kind of crazy talk in my opinion. For 5kb you can have a super nice developer experience using Lit (https://lit.dev)


> Finally, the last thing I would suggest is that writing an entire app in vanilla web components is kind of crazy talk in my opinion. For 5kb you can have a super nice developer experience using Lit (https://lit.dev)

I 100% agree with this. For me it was more of a question of "can I do it", and that was something I wanted to find out. You notice that I ended up having to recreate a significant chunk of lit-like functionality on my own via a base class: https://github.com/jjcm/nonio-frontend/blob/master/component...

I would very much recommend not going full vanilla. Using a library like lit will definitely help making things easier/more polished, and will integrate better with existing tooling.


> writing an entire app in vanilla web components is kind of crazy talk in my opinion

Why?

I've done many.

My guiding principles:

- Avoid shadow dom unless it's a library. Stick with the light DOM and css system of your choice.

- Use lit-html or similar for rendering

- Use class properties for reactivity (add a render() call to setters, as needed)

- Ignore attributes entirely. Just use properties.

- Don't bother with composable components and slots. You generally don't need them

- Use a nice router like vaadin or ionic or similar to hoist components and support deep linking

- Let components maintain their own state. Structure the dom so that it's easy to grab state from a component with querySelector. If this doesn't work, I have a little state lib called ApplicationState[1] that works great.

- Really think about what needs to be a component vs normal html. Don't overdo it with components.

- Structure the app with high level "scene" components that map to URL deep links, and app components that you use to build the scenes. Scenes are targets of the router.

I've been doing this for years for many apps for many clients. Blazing fast, simple, no framework churn, no compilation, no framework download or overhead...

It's pretty tough to make myself use a framework at this point.

[1] https://claytongulick.github.io/applicationstate/


I didn’t suggest for a moment you couldn’t. I said it was a bit of a crazy decision to take.

The entire reason I said that was because there is going to come a time after you have built probably your 5th component where you are going to start moving a whole bunch of shared logic into a base class that extends HTMLElement and that is the point you should probably stop and just bring in Lit at around 5kb total because they already did exactly what you’re doing and they almost certainly have done a better job with a bigger team and access to browser engineers with thousands of existing users and a bigger test suite with better documentation and well.. you get the point.

A lot of your argument seems to be quite focused on the idea that frameworks are some heavy weight thing which is perfectly true in many cases. But other options exist, and with a 5kb-10kb library download budget those arguments don’t carry a lot of weight.


> after you have built probably your 5th component where you are going to start moving a whole bunch of shared logic into a base class that extends HTMLElement

I kind of thought this too at first, and started down that path several times. I actually wrote a whole framework similar to Lit early on, thinking the same thing.

What I've found over time, is 99% of that is YAGNI (You ain't gonna need it).

All my components just extend HTMLElement directly.

I explicitly dislike Lit because you lose control over the component lifecycle. I don't find it easier, I find it harder - especially when you're mixing in pure js libraries like draggable or whatever.

I prefer having to call render() explicitly, and controlling when/how that's done. At the end of the day, it's not actually any more code.

> a better job with a bigger team and access to browser engineers with thousands of existing users and a bigger test suite

Yeah, I don't need all that to show some interactive markup on the screen and organize code well. That's really what WC's are for me - just a convenient unit of encapsulation for vanilla JS/DOM stuff.

Lit is cool, so's stencil. I just don't need it.

lit-html, however, is probably my favorite piece of tech in the last 5 years. I've been using it since it was originally created and was only like 200 lines of code.

All that code I wrote is still working great, and hasn't needed any sort of update. On the other hand, if I'd gone with the Web Components Framework Of The Day, I'd have done Polymer and caused a massive headache for my clients.

Many people were making the exact same arguments you were about Polymer back then.

And then LitElement.

And then Lit.

Lit 2.0.

Now Lit 3.0.

Same story with <fill in your framework here>.

Angular 1.5 anyone?

Framework churn can kill a company.

I code to standards, keep it as vanilla as possible, and prefer libraries over frameworks (though sometimes the lines get blurry there - looking at you Ionic).


What churn are you referring to?

I’m quoting directly from here: https://lit.dev/docs/v3/releases/upgrade/

“For the *vast majority* of users there should be no required code changes to upgrade from Lit 2 to Lit 3. Most apps and libraries should be able to extend their npm version ranges to include both 2.x and 3.x, like "^2.7.0 || ^3.0.0".“

And here is v1 to v2 for completeness sake: https://lit.dev/docs/v2/releases/upgrade/

Most of your examples are kind of odd. One of them was a brand change that involves no code at all.

There is only one meaningful bit of churn in there which also was an overlay of the Web Platform itself.

Polymer was a WebComponentsv0 library

Lit is a WebComponentsv1 library.


"vast majority of users", "should be able to extend".

What are the cases when this easy no code upgrade fails?

And yes, v2 update is quite a breaking change

> Polymer was a WebComponentsv0 library

It wasn't. It got upgraded to v1 almost immediately


> What churn are you referring to?

I think most developers are very familiar with the framework churn that I'm referring to.

In my case, I've been dealing with it since the 90s.

So my biases are there for a reason.


> Performance isn't as big of a win as I'd have hoped.

Is performance a win at all? I would expect performance to be worse than using a regular web framework (React, Vue, Svelte, etc). Because these tend to get their performance from batching DOM manipulations across the entire page, and you can't do that will web components.

I figure web components are pretty much dead in the water for this reason alone. I guess they can be useful if you just want small "islands" of functionality rather a fully client-rendered page.


These days, batching DOM updates doesn't give you as big of a win as it did in the past (browser tech has improved, browser engines do more batching under the covers, etc).

Also web components tend to use more modern layers of the web stack (style isolation, shadow DOM, etc) - which allow the browser to perform more optimizations, as well. I think we'll find that they become more performant over time. Also consider that some "native" html components are effectively implemented the same way as web components these days.

Often you'll find that React/etc are perf hits (vs finely tuned components) because their declarative nature tends to lead to unnecessary work …which is totally fine 99% of the time, because the productivity win from that is HUGE.


Did you see the performance issues also on web components that didn’t use shadow dom? I noticed this performance wall as well, but I always put it down to shadow dom being heavy. Now I’m wondering if it is the instantiation itself that’s heavy.

For state mgmt I have noticed the same problem and was thinking about trying to take a page out of desktop development’s playbook by having a window-level message bus that all components subscribe to and filter data from, and every state change being published on that message bus.


ShadowDOM is actually a big part of the reason where the perf comes from because the universe of what actually needs to be considered in order to get to the eventual answer of what style properties should any given element actually have is tiny due to the fact that it is encapsulated.

That and the the other big win comes from using native compiled C++ browser code to implement large chunks of what libraries typically provide in userland JS.

React is probably the worst offender here as it for all intents and purposes brings its own implementation of both DOM and events. It’s just an outdated architecture choice that made a huge amount of sense at the time but nobody would do that today if they were building a front end library from scratch.

Finally regarding your point about the message bus idea you might want to take a look at the BroadcastChannel API if you aren’t already familiar with it. Sounds like it might be what you’re looking for.


Broadcast Channel API - unbelievable that it has such a wide support.

Really amazing. Thank you for this. Didn't know that.

OP above or anyone else can say anything about routing in context of web components? Deep linking? Any pointers?

Noob backend guy here.


One approach I don’t mind is to just make a HTML file per screen in the application and route like the rest of the web.

When you bring in modern things like service workers and the prefetch API you can still very much keep the speed that is traditionally associated with SPAs.

Otherwise I’ve seen good things said about both of these options:

1. https://github.com/vaadin/router

2. https://github.com/lit/lit/tree/main/packages/labs/router

Both follow the mental model of mapping a URL pattern to a component fairly intuitively.


One file per screen is actually awesome. That's the "MPA" many frameworks are boasting about.

The big win here would be that if you have a huge app (let's say an ERP kind of app that has too many screens and dialogs and what not) then that can be easily decomposed into separate pages that are far more manageable.

You can easily wrap these pages up as Electron/Tauri app or Capacitor etc for mobile.

Deep linking however would be interesting in that if someone pastes a URL, we have to load the exact screen/dialog etc.


I like to keep a mental model that a page level component uses URL parameters the same way I would write a CLI application reads in arguments.

Not at all meaningfully different from say

void main(List<String> arguments) {

runApp(MyApp(arguments));

}


> since you can't pass complex objects as attributes like you can in jsx

But you can!

Here's an example of passing complex objects as attributes (look for zx-listeditor): https://github.com/wisercoder/uibuilder/blob/master/WebCompo...

And here's the web component itself: https://github.com/wisercoder/uibuilder/blob/master/WebCompo...

And here's the tiny (500-line) lib that enables it: https://github.com/wisercoder/uibuilder/#jsx-for-web-compone...


"You can pass complex objects using web components, if you also use something other than web components" isn't really all that much of a defense of web components.


It is 223 lines of code: https://github.com/wisercoder/uibuilder/blob/master/dist/uib...

You object to this tiny amount of code?


How do you make this work with frameworks like Svelte which, when server side rendering, cast all props to string (!) attributes?


That should be an easy bug fix in Svelte.


Since you mention that state management is an unsolved problem with Web Components, I thought I would share a project that aims to bring a solution: https://github.com/launchscout/live_state. The basic pattern and idea of LiveState is "dispatch events, subscribe to state". The events and state updates are sent over a websocket connection, and the front end and back end libraries are a thin layer over Phoenix Channels. Currently, event handler functions are written in Elixir, but work is underway to allow them to be written in any language that compiles to WebAssembly.


> With web components it's the wild west, and since you can't pass complex objects as attributes like you can in jsx, you end up doing a mix of attributes, events, and calling class functions directly.

Or you just write a 'value' getter and setter and be done with it. I write most of my web components to operate like a form component. Forms have state. Forms have mechanisms for gathering state from all components and saving them into a single object. Forms have a means of restoring all that state.

You _barely_ need a layer of abstraction to handle all this. I've honestly never understood the "state management problem" or why anyone would think a framework is the way to solve it.


I don't expect my preferred JS framework to remain the same though. I know that it's short-lived. I like that. Moving forwards, making progress, and improving are why I use React, Vue, Svelte, etc. I don't want something that's static right now, because none of the available frameworks (including Web Components) solve problems particularly elegantly.

If the argument is that a site made with Web Components will outlast a site built with a JS framework then I'd be tempted to take that bet. I honestly think it's more likely that some part of the Web Components tech stack will be removed from Chrome, Safari, and Firefox in the next 20 years, consequently breaking apps built with them, than JavaScript will change in a way that means a React 16 app I wrote 2 years ago will break.


> I [...] think it's more likely that some part of the Web Components tech stack will be removed from Chrome, Safari, and Firefox in the next 20 years, consequently breaking apps built with them, than JavaScript will change in a way that means a React 16 app I wrote 2 years ago will break.

Hmm. I think you've specified a bet you are likely to win, but one that's nearly meaningless. Perhaps if you fully lock down all dependency versions your React 16 app will not break, but that's a little more like running an old program in a VM or an emulator than "I can still work and hack on my React 16 app."

A more meaningful bet would be, "can you still develop on a React ZZZ app vs. can you still develop on an app built with web components."

If I got to pick the terms of the bet (to favor my viewpoint XD but also to make it more meaningful), they'd be "would updating a React app to catch up on N years of dependency updates be more or less effort than updating a web-components built app to catch up on N years of dependency updates"; if you keep your web-components built app from having a bunch of weird dependencies, I think the odds are very much in favor of the React app taking more effort to update.

Basically, betting on browser vendors to be less likely to break backwards compatibility than the authors of React.


> I honestly think it's more likely that some part of the Web Components tech stack will be removed from Chrome, Safari, and Firefox in the next 20 years, consequently breaking apps built with them

That already happened.

HTML Imports got deprecated (in favor of a JS-only solution), though Firefox already implemented them.

Custom Elements v0 was deprecated even though Chrome implemented it and hastily re-wrote Youtube with it. They had to wait ~4 years to remove the implementation because it took Youtube that much to switch.


The v0 part of it should mean none of that was a big surprise. It was an early prototype, it’s stable now.


v0 (IIRC) was not called v0 when it was released. It was called "custom web components". The release of a new version of custom web components is what caused the re-name to `v0`, with the new version being called `v1`. So you built on top of one version to be told later that you'd participated in a beta (unbeknownst to you).


hmm. doesn't stuff like this happen every time that chrome implements some interface but other browser vendors don't get on board with that specific version? doesn't this happen... kind of often? isn't it apparent that there's a risk of this happening whenever chrome implements something before there's standards agreement?


> doesn't stuff like this happen every time that chrome implements some interface but other browser vendors don't get on board with that specific version?

Yes. What rarely happens though is that Youtube gets immediately rewritten with the new tech.


shrug one arm of alphabet pushes through changes to Chrome without standards consensus, another arm of alphabet makes a poor bet on it.


Correct me if I'm wrong, but I think running old code and not updating the dependencies might make your site vulnerable to security vulnerabilities that get discovered over time and fixed with new versions of libraries. So if you want to keep your code secure you will need to update libraries. But those old versions of those libraries will stop being supported, and known vulnerabilities will start to accumulate that have no fix. And attackers will probably have programs scan the web for websites with known vulnerabilities and automatically attack them.

Versus if you use a library or platform (like Web Components) that cares a lot about backwards-compatibility, they will maintain the security while also supporting your old code for longer.


I shifted my focus from technology to people. If I'm starting a new project, I'll look at what the people who'll work on the project know. If there's a common denominator or best practice, like how React is nowadays for frontends, I'll just go with that. I don't really sweat these technical decisions, because the team composition, or the job seekers' market, or StackOverflow's technology top list answers there questions with ease.


I get that and I think it’s pragmatic. But if everyone thinks like you’re suggesting, we’ll all be using react forever, even if there are better answers out there for how to build our software. If you want to use whatever is popular, that means you depend on others to find good technology solutions and make them popular in order to improve your tech stack.

Put another way, this strategy puts you firmly in the “mid to late adopter” part of the adoption curve. Articles like this (and indeed much of this discussion) is largely targeting people who are earlier adopters.


I think you hit the nail on the head on the adoption curve point. I indeed am a later adopter, and lately consciously so.


> But Markdown has a secret weapon: you can write HTML inside of it! That means any fancy interactive diagrams I wanted to add would be just as portable as my the rest of my Markdown as long as I could express them as plain HTML tags.

You can also use MDX and achieve exactly the same thing. Web components the technology don't actually help here; what the author cares about is the interface between their markup and some piece of code that applies runtime functionality. Web components are an implementation detail here: whether you're referencing a React component or an Astro thing or a web component when you type a name between some angle brackets, it really doesn't matter: the point is that _some other thing_ is invoked.

The downside to web components here is that they can only be run on the client, for all intents and purposes. There's no way to pass server-rendered shadow dom content on the server to the client, so even if your web component is fully non-interactive, you still need JS on the client in order to render it. That's not the case with other frameworks.

I'll say that the author's point isn't wrong: web components as a way to codify interfaces between chunks of code is quite possibly the best, most durable way to accomplish that goal. BUT! On the server, web components do you no favors. They don't render, they are a cumbersome interface, and your code is already entirely written in a way that you can (hopefully!) work with. Which is to say, if you have Astro on the server, please keep using Astro! Or react, or vue, or whatever.

Where web components shine is on the client, when you have a component from a third party that might not be written in your framework of choice. You don't need to know about the framework the component you're putting on the page was built with. You just use a HTML tag and it works. The mechanism of the interface is uplifted to the browser level, so you don't need two frameworks to speak each others' implementation details.


> The downside to web components here is that they can only be run on the client, for all intents and purposes. There's no way to pass server-rendered shadow dom content on the server to the client, so even if your web component is fully non-interactive, you still need JS on the client in order to render it. That's not the case with other frameworks.

I thought you were going to argue that there is no way that a tag like <my-component></my-component> magically acquires all its inner html on the server all by itself. That it would need some kind of tool to help it. In that, I suppose, you are right. Although that tool can be literally any server-side templating engine that will fill <my-component> with the initial html it needs to bootstrap.

But server-rendered shadow dom can absolutely be passed to the client. It is called declarative shadow DOM; and it works in all major browsers other than Firefox; and Firefox is working on it right now. There's also a polyfill.


> Although that tool can be literally any server-side templating engine that will fill <my-component> with the initial html it needs to bootstrap.

If you need to add a templating engine to generate your markup, you're really just replacing a framework with web components...and another framework. Which is half of my point: you aren't getting rid of a framework by choosing web components.

> it works in all major browsers other than Firefox; and Firefox is working on it right now. There's also a polyfill.

https://bugzilla.mozilla.org/show_bug.cgi?id=1712140

"Obviously not a commitment to implement, but potentially worth reevaluation" is not "working on it right now", unfortunately.

Here we are again, however, in that a completely non-interactive web component still needs JavaScript to render because you need a polyfill to take static, server-rendered HTML and put it in the shadow root. Again, it begs the question of what purpose web components are serving here anyway. The developer has to bend over backwards for both the server side and the client side and there's no meaningful reduction in code at all for either the client or the server.


>> But Markdown has a secret weapon: you can write HTML inside of it! That means any fancy interactive diagrams I wanted to add would be just as portable as my the rest of my Markdown as long as I could express them as plain HTML tags.

> You can also use MDX and achieve exactly the same thing.

I would like to point out that plain HTML also has this property.


Sure, and you could hand-write your blog posts in a hex editor so that the binary data can just be pumped out over the wire. Markdown generates HTML. MDX generates HTML. Use the tool that brings you joy and makes your life easy.

In any case, the point is that referencing another piece of code from your markup can be done in a number of ways, and the way the author chose has an upside but also a significant downside.


> There's no way to pass server-rendered shadow dom content on the server to the client,

There is a proposal for that, although nobody knows whether it will survive in the long run. https://developer.chrome.com/articles/declarative-shadow-dom...

BTW: the polyfill for this is rather easy, so you may be able to use it even browser today haven't support it now.


It is supported by chromium already and Mozilla has said they'll be working on it


I like web components especially with the nice tooling that comes with lit, but agree that the lack of server-side rendering and hydration makes them impractical to use compared to other server side progressive enhancement libraries like Stimulus and Alpine. Server-side renderable web components would open up a lot of possibilities for better user experience for multi-page apps.


Yeah. The JS world is still so hung up about fat clients having all the control that it's missing all the interesting stuff happening in the server world. Rails Hotwire, Phoenix Liveviews, Laravel Livewire, etc. These solutions can solve 80% of your front end with minimal JS and almost no DX complexity.


Isn't it possible that both the frontend and backend are maturing & more capable? Isn't that what we want?

I've built some feature-rich FE apps that read and write to dbs & object stores with no servers needed! Very portable, the only install step is to upload a few files. They can be run right from a simple CDN. And they are super fast.

Most FE devs I know are actually familiar with Hotwire and friends but to them those stacks would add DX complexity. I think sometimes people say "complexity" when they just mean "unfamiliar". Both FE and BE can be way overly complex, but neither needs to be.


> I think sometimes people say "complexity" when they just mean "unfamiliar".

I do mean actual complexity.

With something like Hotwire/Livewire you don't need APIs anymore. You also can scrap client-side fetch() code and state management. There are some features that will still need some client JS but these will be a minority of use cases (if at all).


Complexity has to exist somewhere, either in the engineer's hands, or swept under the rug for the framework to perform its magic on (really thinking about the Rails ecosystem here). When things go wrong, it's nicer, in my opinion, to have more control, especially in this fast paced clients-want-it-now environment.


In my experience, the complexity with most frontend development is accidental by way of splitting state between client & server.

If you manage to consolidate nearly all state to the server, complexity reduces by an entire dimension. There is nothing to synchronize anymore. You don't need these universes of delta-detection tools, frameworks, protocols, etc.

In most of our modern SSR apps, the only state the client needs to hold onto is a session token. If we find the client has a wrong session token, correcting this is quite simple. Everything else happens on the server.

Certainly there are holes with SSR (latency), but we haven't run into a real-world scenario where this actually matters enough to introduce entire new universes of hell into our lives.


> especially in this fast paced clients-want-it-now environment

But wouldn't a solution that makes you more productive allow you to deliver faster?

That's what Livewire/Hotwire/etc are trying to achieve. Make developers more productive.

When going full on SPA there's so much complexity you need to solve. Crossing the client/server barrier with APIs, managing state in the client, etc.


> Complexity has to exist somewhere,

What is the complexity you are talking about here, is this the human (programmers) understanding of the system or the design of a complex system itself ?


Yes. Definitely been bit here with ORMs and custom query languages.


You either write HTML in JavaScript or write JavaScript in HTML. Personally, I would rather write everything in JavaScript/TypeScript than sprinkle syntactic sugar over HTML.


No offense, but you're thinking from the JS bubble.

Yes, ultimately you need JS to interact with the DOM but if you look at eg Livewire the orchestration is in the server. I'd be happy to use a similar fullstack solution in JS/TS but afaik it doesn't exist. And it doesn't exist because the JS world is still hung up on full on fat reactive clients which are overkill for the immense majority of use cases.


Liveview and similar frameworks are cool but not great for everything. It's not easy to build an 'offline first' application with it, for example


I agree. These solution are not meant to solve all the front end needs. But they can solve the majority of it (forms, modals with dynamic content, filtered lists, etc).


Nothing is great for everything.


> I'd be happy to use a similar fullstack solution in JS/TS but afaik it doesn't exist.

If you mean, a fully TypeScript full stack solution then you might be correct. I wouldn't know because I tried Deno earlier this year and it wasn't great.

If you mean, a full stack solution that utilizes TS to for both the API and for the frontend then that is a much easier find. Vercel's Next.js provides this out-of-the-box and various other full stack starters and boilderplates exist.

I recently built one using PgTyped and typescript-rest.


It's not about writing the HTML, it's about managing the state only in one place .


Is it not just the same tradeoff space we've been exploring since the beginning of UIs about how thin the UI is? It's not like putting stuff on the server side via livewire doesn't have strong disadvantages around latency etc.


> It's not like putting stuff on the server side via livewire doesn't have strong disadvantages around latency etc.

It's exactly the same latency that a request to an API will have.

Obviously Livewire is not a good option for interactivity that happens exclusively in the client.


> It's exactly the same latency that a request to an API will have.

Every interaction in a livewire type system requires a round trip - that's not true for SPAs. Let's say I'm developing a node based editing UI with drag and drop that lets me connect things. How on earth are you going to make that work with livewire?


> Every interaction in a livewire type system requires a round trip

You’re wrong on this. You’d use Alpine and do the interactivity client side. If you don’t miss use the tool, Livewire is supposed to reach to the server in the same situations an SPA would reach to the server (updating or refreshing server state)


Obviously Livewire wouldn't be a good fit for that (extremely rare) use case.


In those cases you use alpine, and do the interactivity on the client side.


Preach!

I'm still keen to learn more on the Inertia side of Laravel, but Livewire (and especially with Filament in the mix) just feels insanely productive as a Laravel dev.


Why do people keep hiring front-end specialists, in that case?


Because front end specialists only think about the front end.

The tide is slowly turning though with Next, SvelteKit, Remix, etc. But still these frameworks are basically just rendering HTML and going full on fat client which is overkill for 80% of interactivity in web app but adds a lot of unnecessary complexity.


Because a) they're available and b) people think it's a black art.


c) backend devs often proudly hold contempt for front end work and do the job poorly


They don't want to get involved with tech that goes out of date every year.


As a primarily frontend-developer, I can attest to this sentiment. I should add that most backend devs I know understand the basics of HTML, CSS and Javascript, but they're less interested in learning new framework/library/template system constantly. I have to admit, I share that attitude.

It's funny how webcomponents alone are touted as an "alternative" to a framework, despite only being one component (no pun intended) of something that solves the problem of UI state-synchronization on the browser. A better comparison would be comparing a combination of custom elements, server-side rendered HTML, and proxy objects to some SSR framework like NextJS, Remix, etc.


I love that trope honestly. It's a great way to discover bad developers without having to test them first.


The title is probably correct, but not sure it matters. Most applications will not live that long. I recently tried using Web Components, and something that is very simple in any framework like using a <slot> was, um, eh, incredibly confusing and complicated to setup. This maybe doesn't matter if your component is just a <pixelart-demo>, but if you're building an application in JS then using slots is for me a critical feature because it allows me to have composable components. Debugging with "shadow dom" was also really confusing in dev tools.


> incredibly confusing and complicated to setup.

And some being almost impossible to work correctly without MutationObserver or some polyfill of it. The renderProp in react (or scoped slot in vue) is so commonly used to inject data from the parent component into child component. But replicate such behavior in webcomponent is simply... impossible without MutationObserver hacks. The assumption of web component that child/parent component never need to know the info of each other just don't make sense in real world.

And the assumption that child component is always loaded and initiated regardless of parent component is also falsy in most frameworks. In most frameworks, the parent component decided whether child should be actually loaded or initiated.


Web components might be better for writing isolated and reusable components, but for gluing stuff together to make your application work, the DOM API is just garbage. It was made to edit XML documents and it shows.

Also, one reason I don't make web components even for isolated, reusable components: No editor properly picks them up for things like autocompletion of attributes and event names or checks for typos.


They will also require a cobbled together list of dependencies to make useful, and those dependencies will probably not be maintained as well as React.

I worked in a shop that followed this philosophy. Every single UI component was a web component with its own npm package to install. It worked fine. There was zero benefit. There's still zero benefit today 6 years later. You're optimizing for a future which will most likely never come.


HTML/CSS sites will outlive it all. Because they're actually the text, images, layout all in static things that can live forever without being touched and without any need for complicated execution of code or mantaining of obscure rapidly changing pseudo-standards. (*1)

If you want to make sites and have a skillset that last, learn how to make progressively enhanced HTML websites. Anything like Web Components (where you invent useless non-defined HTML-elements-with-hyphens and then define them after executing a bunch of Javascript), Javascript frameworks (where you don't even pretend to involve HTML) will last only a handful of years.

(1*: at least until HTTP/1.1 support is removed from browsers)


What part of web components don’t meet the definition of progressively enhanced?


You might be able to do progressive enhancement with web components but the vast majority, every web components site I've ever encountered, just end up with blank gray areas when the JS is not run to define them. That is far from progressive enhancement.

It's a bit like "communism". You can say web components can be great or whatever, but everyone's every experience with it is very bad.


Did you see what I used them for, though? How would you make a tutorial article with interactive demos without JavaScript?


I didn't see it. All I see is "JavaScript is required to run this demo." but the rest of your text is visible and that's pretty exceptional for a web components site. Usually even the text doesn't exist unless javascript is run. So thanks.

To address your point: the vast majority of web sites are text and images, not executable applications. Interactive tutorials are niche. Cool, but not something I'd base my entire web design ethos around.


I mean, I feel like you can see from my website that I’m not basing my entire web design ethos around it. Other than the interactive demos that literally could not function otherwise, the whole thing works perfectly fine without JavaScript. That’s not an accident!


I was excited for web components, but the API was lacking (the final tipping point that led me to build Joystick [1]). I just couldn't get on board with a web-standard that eschewed HTML in favor of stuff like this [2] where list items are attributes. The hyphenated namespace thing has always made my eye twitch, too (silly, I know).

[1] https://github.com/cheatcode/joystick

[2] https://github.com/mdn/web-components-examples/blob/main/edi...


    <editable-list
        title="TODO"
        list-item-0="First item on the list"
        list-item-1="Second item on the list"
        list-item-2="Third item on the list"
        list-item-3="Fourth item on the list"
        list-item-4="Fifth item on the list"
        listItem="This will not appear"
        add-item-text="Add new list item:"
    >
    </editable-list>

You could easily do this a different way, if you still wanted it to be an attribute <editable-list items='["first", "second"]'> and pass json to a single attribute. Or make child <list-item>'s.

One thing about web components though, having shipped web components for an internal design system, is that a lot of people don't understand the difference between html attributes and the properties of the underlying javascript objects. In plain HTML, or most server rendered templates afaik, there's no way to pass non-string data declaratively like you could with say Vue where you can choose property vs attribute to bind data.


> You could easily do this a different way

Yes, but that you have to make a choice means the design is poor. That's why stuff like React (imo) is a failure: there's a kajillion ways to do the same thing which end up creating dogma and sloppy/inconsistent code (read: bugs). Web Components—as far as I've seen—are making the same mistakes, but even worse, as a standard.

As a web standard, Web Components should have been more carefully crafted. There's zero reason the spec couldn't have allowed me to wrap a normal <li> tag in the example above. That it doesn't means, somewhere along the road, a compromise was made that shouldn't have been made.

The problem with all of that is when you introduce new web developers (who start by learning vanilla HTML, CSS, and JavaScript), as soon as they get to wanting to build more complex stuff (read: components), they essentially have to "unlearn" much of what they learned.

Why does that matter? Paraphrasing Uncle Bob: because the rate of new developers doubles roughly every five years, that means half the programmers in the world have < 5 years experience. If they're learning bad/inconsistent patterns from day one, that means the quality of the software they build (and God help us, the tools they create later) is on a permanent downward slope.


Literally any framework that allows attributes/props, and child components has various ways this could be done. Vue, React, Svelte, Angular, all of them.

There are many issues with Web Components, but I don't think this is one of them. The real pain doesn't start until you want to do something like:

  <form>
    <my-input></my-input>
    <my-button></my-button>
  </form>
and have everything behave as expected.


> There are many issues with Web Components, but I don't think this is one of them.

You described another version of the problem I'm getting at. You should be able to use vanilla HTML, but you can't without hoop jumping.


That's not another version of the problem.

It's pretty clear that you don't have a substantial amount of experience with Web Components, but have a strong opinion about them nonetheless.


You could do the same weird attributes thing with props in React. Does that make React's design equally poor?

I don't know how you can prevent bad component designs like this.



    const EditableList = ui.component({
      render: ({ props }) => {
        return `
          <ul>
            ${each(Object.keys(props).filter((p) => p.startsWith('list-item-')), (p) =>
               `<li>${props[p]}</li>`
             )}
          </ul>
        `;
      },
    });

    // Usage:
    ${component(EditableList, {
        ['list-item-0']: 'First item on the list',
        ['list-item-1']: 'Second item on the list',
        ['list-item-2']: 'Third item on the list',
        ['list-item-3']: 'Fourth item on the list',
        ['list-item-4']: 'Fifth item on the list',
    })}
edit: used each(), which doesn't change the point that you can make a bad component API in any framework.



Re: your edit, that's not a bad component API, that's bad JavaScript (intentionally written by the author, in this case).


This is exactly my point. The MDN element is bad (the component has a bad API), and made bad by the component author, not the web components APIs.


Which highlights that there is a lack of clear prescription around how to handle a list in a component at the (Web Components) API level. Contrast that with what I linked from my own framework where there's zero uncertainty as to how to handle a list.


[2] Is just a bad example that you could build with anything, and had nothing to do with the spec. They could have chosen to take data as child elements, or as a JS object. Individual attributes like that is a bizarre choice and shouldn't reflect on web components.

The web component APIs are low-level and what you need to achieve interop with the browser. Most developers use something like https://Lit.dev


> Is just a bad example that you could build with anything

This is the go to "defense" I often hear from web component proponents.

If even MDN cannot come up with a better example, something's wrong with tech, not with how people use it.

> The web component APIs are low-level

It's not. It only got labeled low-level after the initial failure to attract any developer mindshare. And then it got rebranded as "aimed at library and framework developers". Though it barely got traction there either because it offers nothing lib and framework developers want.

> Most developers use something like https://Lit.dev

The irony of writing this under "Web Components will outlast your framework"...


> This is the go to "defense" I often hear from web component proponents. > > If even MDN cannot come up with a better example, something's wrong with tech, not with how people use it.

It's not a "defense" it's a very wacky demo and I can't think of a single reason why you'd ever design a component this way. You could also design a React component or Angular component this way, and just like with web components, no one does, because it doesn't make sense.

I can't say why MDN decided to do this, but this is literally the only time I've ever seen a list represented as individual attributes.

> It's not. It only got labeled low-level after the initial failure to attract any developer mindshare

This... just isn't true. Web component APIs are things like customElements.define(), HTMLElement.attachShadow(), HTMLElement.connectedCallback(). These are objectively low-level compared to things that frameworks give you. Branding (whose?) has nothing to do with it.


> It's not a "defense" it's a very wacky demo and I can't think of a single reason why you'd ever design a component this way

Because it literally is the example on MDN?

> This... just isn't true. Web component APIs are things like

Yes, yes they define those APIs. They are both too verbose, badly designed and low-level to use them directly, and they are too high-level, badly designed and useless for most frameworks to use them as the foundation for anything.

However, even if we view them as "low-level compared to frameworks" they are still:

- extremely high-level (as all DOM APIs)

- were lauded as high-level and the end of all frameworks for years before being rebranded as "these are for framework authors akshually"

Or, to put it simply, they are as "low level" as React's class-based APIs of yesteryear.


> were lauded as high-level and the end of all frameworks for years before being rebranded

Sources please? I've never met a single person that thought this.

> Because it literally is the example on MDN?

You're very stuck on this bad example. With even a cursory understanding of how Web Components work you can understand that you can recreate the same component accepting the same props in any popular component based framework. Or using Web Components you could do this example component just as many different ways as you could with another component framework.

There are many reasons to not use Web Components. Outside of some specific use cases I wouldn't use them. "A single MDN example weirdly used multiple attributes for list items, instead of child components or one attribute" is not one of them.


> Sources please? I've never met a single person that thought this.

Web Components are 12 years old this year. They were lauded as the be all end all of web development to replace all frameworks for 4-5 of those years.

> You're very stuck on this bad example.

Because it literally is in one of the few authoritative places documenting web technologies.

It's not w3schools or some personal blog. I go to MDN to lookup or verify information on web technologies.


I would like to love web components but they are still quite sucky to use (stringy attributes, bleh), especially if it's not your team who produces them.

And some super basic stuff like buttons in forms is still an unsolved problem:

  > Form-associated custom elements: being a submit button
https://github.com/WICG/webcomponents/issues/814

opened 4 years ago and representatives of major browsers still don't have an answer


That form issue is actually resolved with full cross browser support already https://developer.mozilla.org/en-US/docs/Web/API/ElementInte...

Also you don’t need to pass objects as HTML attributes, I think people pick that up coming from React but the browser lets you pass around objects between components just fine by using properties


Can you provide me with an example please? I've seen the ElementInternals api but still don't understand how it should help with the case of being able to submit the form by hitting enter in one of the inputs (which is standard html behavior).

I wasn't able to find working example anywhere and all the discussions around the issue are still open which leads me to an assumption that this is in fact, still unsolved.

https://lit.dev/playground/#project=W3sibmFtZSI6InNpbXBsZS1n...


An adult mayfly will outlive most Javascript frameworks.


React is 10 years old


I enjoy and use react, but I wouldn't call the modern react api (hooks etc) 10 years old.


Even hooks are almost 5 years old, there's been some changes to the hooks API but it's largely the same.


It is good that I wrote "most" and not "all", then.


I often see novice developers making the mistake of comparing React to Web Components, to htmx, to Qwik, etc.

React is not an equivalent of Web Components, but neither it is a front-end Web framework: it is neither a framework, nor it is specifically for the Web. What it is is a fairly small and general reactive GUI library[0]. Together with ReactDOM—a separate library—it can be used on the Web, but React itself can be used to render anything anywhere if you provide a suitable reconciler.

As such, React (itself as old as Web Components) may well still be there whether or not the state of the art in front-end Web development moves on to whatever the next stack might be.

[0] The distinction between frameworks and libraries, which tends to be lost on many fresh developers as well, is out of scope here but vital when it comes to software architecture.


> React is not an equivalent of Web Components, but neither it is another web framework. What it is is a tiny and very general reactive GUI library.

As for tiny, react-dom currently stands at 42kb minified gzipped. A tiny library would be about 1/10th the size (compare with preact or svelte).

Also, react has nasty rerendering habits, which makes if feel not so tiny at times.

But more importantly, have you read React docs recently? Have you seen how the official position of the core team is that if you are starting out with react, you should just pick a framework (Next or Remix)? Have you seen the extra complexities that these frameworks start to introduce (client-side state management in the age of server components, anyone)? React is no longer a tiny and very general reactive GUI library. For a tiny and general reactive GUI library, look at Lit. React, meanwhile, is attempting to become a kitchen-sink.


React promoting the use of frameworks by default is especially problematic because these frameworks are maintained by people who have profit incentives (either due to investor funding and/or because they sell products based around the framework). They aren’t just open source React frameworks; they’re open source products for companies using them as business engines.


This is factually incorrect. React is 6.4kB minified. What you are talking about is a bundle of React and ReactDOM.

Remember: these are libraries. They compose. You can use one and not the other, e.g., if you are not rendering to DOM (and in fact even if you are rendering to DOM, but you come up with something smaller and more performant than ReactDOM that suits your requirements).

If you are saying “React is bigger than X”, you are comparing apples to oranges unless X can also do what React does. Which, per my previous comment, none of those frameworks can.

> more importantly, have you read React docs recently? Have you seen how the official position of the core team is that if you are starting out with react, you should just pick a framework (Next or Remix)?

It’s a combination of two factors:

1. Being a library, it’s by definition open to frameworks being built on top of it that facilitate library’s integration in specific solutions in specific ways. Without getting into the nitty-gritty of what it means to be a library or a framework, those frameworks add constraints on how the library is used, but they add value by providing scaffolding and streamlining some use cases. Therefore, it could sort of make sense to tell a novice front-end Web developer to just use a framework to get things done.

2. Unfortunately, React is increasingly being influenced by commercial platforms that use those React-based frameworks (e.g., Vercel). I believe some of the original React developers moved from Facebook to some of those companies. Those companies have vested interest in sending people their way, and I suppose they are or they feel entitled to use React’s reputation for that. I also think they are incentivised to not make React’s documentation particularly easy to use, to keep some features private while using it themselves (cf. RSC) for as long as they can get away with, etc.


> This is factually incorrect. React is 6.4kB minified. What you are talking about is a bundle of React and ReactDOM.

If you look at my comment again, you may notice that I wrote "react-dom". I checked before writing.

> If you are saying “React is bigger than X”, you are comparing apples to oranges unless X can also do what React does. Which, per my previous comment, none of those frameworks can.

Does preact need a preact-dom library ten times its own size? Does lit? What is it that they do not do?


> Does preact need a preact-dom library ten times its own size? Does lit? What is it that they do not do?

No, but neither does it work outside of DOM. As I wrote in my first comment, you can use React anywhere (native apps, embedded LCDs[0], etc.), as long as you provide a suitable reconciler. It’s a tiny general reactive library that is neither a framework, nor is geared towards DOM/Web in particular. As far as I know, the same cannot be said about Preact.

[0] https://github.com/doodlewind/react-ssd1306/blob/master/docs...


> No, but neither does it work outside of DOM.

I know. This thread was specifically about the web though. Web components?

If you put React on the web, it is only fair to consider it together with react-dom in all the comparisons. Without a rendering library, React by itself, however small or generic, is not of much use. So what the absolute majority of people mean when they say "react" in the context of building things for the web, is the react/react-dom combination.


> I know. This thread was specifically about the web though. Web components?

That is exactly the point. This author compares Web Components to React and Astro. Web Components is a spec. React is a general-purpose XML-based reactive GUI rendering library. Astro and Next are frameworks. Next uses React, and Astro can use React. I think you can use React and ReactDOM to render custom elements on the Web already (or will be able to soon), nothing fundamental prevents it. Either the author is not experienced enough to understand what is what, or he tries to gather engagement by inciting a holy war using false dichotomies.

> If you put React on the web, it is only fair to consider it together with react-dom in all the comparisons.

React-the-library doesn’t cease to exist if you happen to use it with ReactDOM. It also doesn’t automatically become a framework. In addition, the Web exists within the rest of reality. Even if all of the above contenders were also libraries, if one library works independently of particular medium (e.g., can be used in native applications, etc.) then it exists on another level than any Web-centric library.


React is the Spring framework of the frontend world.


> I often see novice developers making the mistake of comparing React to Web Components, to htmx, to Qwik, etc.

> React is not an equivalent of Web Components

The only people who promote these comparisons and draw these equivalencies are the people who promote web components under the weird mantra of "use the platform".


I think the author was referring about the specific use-case of building a website using static file generators.

In that context I 100% agree with him that if you want to sprinkle some interactivity while keeping your content "portable" and be able to move to the next "CMS" of the future, sticking with web components is a much wiser choice, rather than embracing whatever fancy convenient feature your tool provides (like Astro's islands).

(It is good advice and a well written article btw, thank you for sharing)

I don't think he was suggesting to build your next SPA entirely with web components..


Author here — yes, this is exactly correct (and thank you for the kind words). I think the maintenance cost of dependencies is important to consider, and with web components we have a "native" solution for encapsulating HTML, CSS and JS. That doesn't mean that every project needs to have that as its top priority! Sometimes development velocity/shared patterns/ease of finding other developers is more important, and that's perfectly fine.


But will Web Components of tomorrow be the same as the ones today? I see that, in today's parlance, this is 3 core ideas. Custom elements, shadow DOM, and templates. I fully expect things to be added to that list as time goes on. Not the least because of so many obvious things that are not covered there.

To that end, the question will have to be if you can run the same web components of today on a browser of tomorrow. With the very notable fact that though you can't run components on browsers of yesterday, you can run that old jquery site on browsers of today.


No they won't.

Because React is a view library, not a framework.

Yes, web components might outlive React.

But no, they will not outlive my JavaScript framework, because web components don't replace routing, data layer, testing, authz, server-side rendering, rehydration and whatever else frameworks like Angular/Ember/Next.js/etc do these days.

Rendering a view is a small part of what front-end frameworks do.


React is a framework because it calls into the the components to make them go, not the other way around - the Holywood Principle.

This shows up with restrictions like that you can't mix and match components with different versions of React in the same tree.


Even React homepage calls itself a library, and mentions Next.js/Remix/Gatsby/Expo as React frameworks you can use.


Doesn’t change that framework has a definition that react meets. The renderer runs your code, that’s a framework


Your definition is very...unintuitive to me. Control inversion (the Hollywood Principle) isn't relevant -- many systems which use it aren't remotely frameworks.

Most people view libraries as tools which target narrowly scoped sub-problems of a given solution/application. In React's case, it's a view library -- the V in MVC, for instance. Frameworks are generally considered holistic set of tools which tightly integrate together to form a structured & opinionated approach to the larger solution, e.g the entire MVC approach.

React is widely considered a library. React doesn't tell you how to structure your project, manage its backend communication, handle application state, routing, etc. React is just...not a framework. For any standard notion of what engineers mean when using the term. If you use IoC to distinguish libs/frameworks, you're going to confuse the hell outta people. There are certainly technologies which straddle the line between these terms, but React is not one of them.


> React doesn't tell you how to structure your project, manage its backend communication, handle application state, routing, etc. React is just...not a framework.

Technically it doesn't, but the conventions that grew around it and the availability of learning material effectively produced same default choices, making it a framework via convention.

And I see it as a good thing, because having several competing router implementations is an unnecessary headache.

The React crowd would do good to stop being in denial about this.


React is not a web framework... You think of things like Next or Remix, those are. There's no inversion of control, it's not a framework. Words mean things


React is a framework. There is inversion of control: React calls into component to make them go, not the other way around like a normal dependency.


Have you used React? It doesn't do that stuff for you. You need to call another lib (react-dom) to make it happen. If you are not aware about it perhaps you've used a framework or template not react itself :)


Distinction between library and framework has nothing to do with how much stuff they do. The difference is - as the parent comment said - inversion of control. Can you create React component and take full control of component lifecycle outside of React rendering loop? - if yes, then you can call it a library.

I think React doc, by calling Next a framework, is referring to a set of practices and protocols. But different usage of same nomenclature in the same discipline is very common.


> Can you create React component and take full control of component lifecycle outside of React rendering loop?

Yes? If you create a React component, it does nothing. You define the lifecycle when you call ReactDOM. But you don't need to call ReactDOM. Call whatever you want.


I also like reducing dependencies, but I’ve picked a different approach.

When I use an external library, I link to static production scripts, without webpack or other bundler. I do use babel to handle jsx if needed, but I do it by linking babel via a script tag in dev mode (and with a simple shell script in production).

It’s more radical, not recommended for production use and impractical for anything other than a hobby project. But it’s a way to limit adding new dependencies, or limit reliance on package managers. Additionally, the project can work with as much as a static file server, also for development - so I won’t get stuck on an “npm update” when I return to a project after a break.

Most recent website I’ve built like this is: https://merely.xyz/lenses , list of Sony E Mount FF lenses.

Again, for most cases web components sound like a more practical approach, I plan to explore that long term too.


That's exactly what I've been trying to do for the last few days but get frequently hit by simple JS errors such as import failures, and currently I don't have the time to properly learn the language.

Looking for a way to learn enough to get something up and running. Do you know any source that explains using React this way? I've looked into the source of merely.xyz but I am looking for something simpler that holds your hand.


The web component idea originally had something like 4 basic components.

- custom elements - shadow DOM - html imports ( now dead or at the very least 'resting' ) - html templates

I think it's important to note that you can build/use custom elements ( defining your own tags with encapsulated behaviour ) without having to use shadow DOM nor html templates.

So a simple way to start, in my view, is plain custom elements, mixed in with ES modules and import maps.

Shadow DOM and html templates are not compulsory to get your <custom-tag></custom-tag>


And jQuery will likely outlive both.


as i pass through my incarnations at every conference & youtube influencer king,

i make my proper prostrations to the gods of the hot new thing

peering through reverent fingers I watch them flourish and fall,

and reliable silent old jquery, I notice, outlasts them all


Selecting an element right from the DOM,

With syntax so simple (and not a fork bomb),

No matter the changes in chorus and verse,

Every new framework . . . will make it all worse.

Within your questions and inner for loop,

Is readable syntax (not alphabet soup),

Give up on your promises, avoid callback hell,

Just keep using jQuery - I promise, it's swell!


Maybe COBOL as well. That doesn't mean I want to use it in my day-to-day life.

Washboards might outlive washing machines but I still prefer the latter to do my laundry.


I wouldn't really consider it alive in the grand scheme of things.


According to https://w3techs.com/technologies/details/js-jquery:

> jQuery is used by 94.5% of all the websites whose JavaScript library we know. This is 77.5% of all websites.

This appears to be current data too (Oct 2023). I'm not sure how reliable the data is, but it is congruent with my experience that _a lot_ of websites still use jQuery. It's easy to forget the HN crowd is also in a bubble. If you only read articles here, you'd think everyone is using the latest JS framework du jour, but lots of the web still runs on PHP and jQuery.


Not that surprising actually, since jQuery is bundled with WordPress.


yes, but why on earth would you pick it for something greenfield? The only justification I could see is it being a tool you are personally familiar with.


IMO Web Components generally suck in developer experience but are good for bridging different js projects or web frameworks as the web components are very compatible between js frameworks. You can literally make a thin wrapper to expose your js flavored framework-based component such as react for example and expose it as a web component to another system such as angular 1 for example and it will work pretty well. You could potentially use this strategy to have parallel tracks of development where you can create an entirely new framework from scratch and start to share that functionality in the legacy project while you're in the process of upgrading which could take a long long time in some cases. At least you won't be continually working on the old one and adding more tech debt... although one could argue this wrapper approach is tech debt.


Maybe, but while I love UI components, I really dislike that "web components" conflate and combine multiple things like custom elements, and shadow DOM, etc.

So working with them in real apps, you get a mess of opinions and assumptions like completely isolated styles (no I don't want this! let me use my site's Bootstrap theme!), etc.

Also dealing with string-based attributes/props is a pain. I greatly prefer React/Svelte/Vue for not having to deal with all this.


It's an umbrella term for a set of technologies. Each of them can be used in isolation from the others if you want though. You don't have to use shadow DOM if you don't want it. You don't have to use custom elements if you don't want to either. You are correct though that almost every tool that works with them sort of assumes you are going to use both.


I kinda like this approach. You can change the combination of used APIs for different cases.

"Widget" that you provide for partners to put on their web pages? Of course you'll use shadow DOM, because you don't know the page context, surrounding styles, etc.

A component to share on different parts of your site - you can skip the shadow DOM, because you share common styles everywhere, and probably you want to inherit some of them.


I think in terms of the implementation keeping them separate and composable is very useful. I think the marketing around it could have emphasized it a little more but that's water under the bridge really.


It's fairly easy to choose between style isolation and no style isolation though. Just change the `this.shadow.innerHTML` in the render to `this.innerHTML`. The encapsulation aspect provides some really nice benefits in many scenarios, so having the option of this is quite nice.

A classic example of why this is beneficial is when creating design system components - you typically want these to not be affected by styling on the page, and if you do want them to be styled, you only want them to be styled in specific ways which you can build in via css custom property values (see the accent example the author provides).


> you typically want these to not be affected by styling on the page, and if you do want them to be styled, you only want them to be styled in specific ways which you can build in via css custom property values

Ironically, this proves my point about opinions a bit - our design system is themeable and needs to cover a number of technologies and we want to inherit the app's CSS, not embed the styles or have to specify colors on every component.


There's a strong difference between styles and themes. Theming is quite easy with web components, as long as you have a semantic layer to your design tokens. Since custom properties do cascade, it's quite easy to automatically switch themes while still preventing css-selector clobber issues with styles.

If you're curious on this approach, my site non.io has light/dark theming via this method, and Figma's light/dark mode was loosely based on this approach.


My problem with web components is the jitter they introduce when rendering the page. Sure, you can hide this or fade it with CSS, but it's kind of a dealbreaker for me. Maybe someone can suggest a better workaround? For instance, on the submitted page, I see a jitter for the pixelart-demo component.


There are so many downsides of choosing web components you really need a very rare usecase to justify them. They are an artefact of a time we're all glad to be done with, they force you into OOP so you're doing inheritance acrobatics, add TS and now you're feeding two hierarchies of inheritance that don't quite match and bloat to a 80% of your codebase, making it unreadable, prone to hacks and bugs, impossible to maintain etc. The point of web components was to make components more shareable between frameworks, and code more reusable, but now code written in any of the major FE frameworks is more reusable (a component looks pretty much the same in React, Vue, Svelte, but not with web components).


Webcomponents will outlive React 13? Sure. Will they outlive React entirely or its cousins like Solid and Svelte? Perhaps not.

Webcomponents and React look like they solve the same problem but they do not.

Webcomponent api is pretty shallow. You get connected/disconnnected/attributeChanged call back but gotta write your own property setter and getters, slots, template, shadow dom and that’s mostly it. Shadow dom becomes a pain to work with if something needs to pierce it. No built-in webcomponent api for efficiently applying state changes to dom. All attributes have to be strings and other types need to be parsed.

Mixpanel went all in on webcomponents. They made their own framework on top of webcomponents. https://github.com/mixpanel/panel

Worked on panel lib and webcomponent UI for many years. Webcomponents are not a silver bullet.

The issue with webcomponents is there are a ton of libraries that fill in the missing gaps. There’s not a lot you can do with pure vanilla webcomponent api. Google has their own thing, Microsoft had multiple internal libs across orgs, Reddit does their own thing.

The most standard thing for frontend with wide adoption right now is React.

vanilla webcomponents are good for simple widgets in a vanilla html/css page. To build complex single page applications, would not recommend it. You’d be building you’re own bespoke framework to fill in the gaps.


I find it interesting that the author's premise seems motivated by a self-inflicted churn. Having migrated a simple blog across a dozen of technologies, their conclusion is that <basic building blocks> will outlast any trend?

Surely, yes. But I'd like to observe that a blog like this, one of the simplest web-based entities, could have remained implemented in some of the decades-old technologies and delivered the same experience to the end user.


Why Web Components have not yet taken off?

They always sounded like a beautiful solution how to make all the various web frontend frameworks to live peacefully on the same page.


Because they don't come with router, state management and other support.

When you start adding them, you will be writing enough glue code that will offset a lot of benefits of web components.


because they have a shitty API


Because they don't offer a lot of things that matter to a lot of folks. This is still true 4 years later: https://x.com/Rich_Harris/status/1198332398561353728?s=20


We wrote Puter.com in vanilla js and it's been pretty straight forward. tbh most of the complexity is coming from the backend rather than the frontend.


But will the JavaScript Framework I'm using outlive my application? Most folks would answer yes I think.

The lifetime of apps is surprisingly short.


I dont know about that. The very first project I worked on after graduating is still very much alive last I checked, and I was actually promised that it should only have a lifetime of a few years as it was an incredible fast developed prototype - the feature set and scope considering. I actually left the company because we were two devs and the owner of the company constantly wanted us to work on new features instead of improving the foundation of the obviosuly rushed prototype, but here we are almost 15 years later and the core of it is pretty much still the same thing as when I left (SaaS).


I've recently found out stuff I've built 16 years ago, in ColdFusion and Classic ASP (anybody remember Macromedia Dreamweaver, later Adobe?) is still in use, never mind more "recent" WebForms + jquery stuff...


Which web components, the ones that were deprecated and no browser implements anymore? Ah wait no, you mean the new ones that virtually no one uses, right? While the point of view that ESM and DOM APIs live long-term is pretty good, the specific example is maybe the most infamous for how not true this has been and many call web components Dead On Arrival.

Newer technology on the web does break more often than old JS (maybe, Flash?), for example I have a project that for security reasons doesn't work anymore, Cookies famously also had a big change for security like that, fetch() defaults changed, and AFAIK even performance.now() was capped for Spectre.


Bing Chat is built entirely with Web Components.

(I work at Microsoft on it. You can verify with F12.)


AFAIK - also the browser version of Photoshop.


And Chrome OS, Firefox, Reddit, Internet Archive, YouTube, and a long list of others...


I checked a couple of those quickly;

Reddit doesn't seem to use web components at all? https://imgur.com/a/kzLoGnV

Youtube seems to use 1 web component for every 10 normal components, which is fair: https://imgur.com/a/YIBhLh8


The "normal components" you're referring to are just elements. I don't see the need to track a ratio there. All of YouTube desktop's components are web components.

Reddit doesn't use web component on all pages yet. They have them on certain types of comment pages now and are incrementally porting the rest of their site from React to web components with Lit. They've also built this year's r/place with Lit, and are building other things like embeds on web components.


Reddit has a whole other site if you go there without being logged in. That one is built with web components.


GitHub also uses web components.


I tried to try Bing Chat (https://www.microsoft.com/en-us/edge/features/bing-chat here, right?) and ironically it asks me to download the whole Edge, AND from the screenshots it seems like it's a browser part? extension? No, thanks.



> Ah wait no, you mean the new ones that virtually no one uses, right?

This is exactly the point. Virtually no-one is using them (well, except for Microsoft, and Google, and Adobe, and Github, and Reddit, and NordHealth, and a bunch of others), whereas they are far more future-proof than any of the much more popular frameworks.

It will all change with time, of course. Just like there is no reason now to depend on jQuery. If only I could restart our app again, I would never have chosen React for it. And it worries me when I think how we are going to migrate off of it.


Most of those use Lit right? I’d be afraid to choose a library created by Google


> I’d be afraid to choose a library created by Google

I wouldn't :-) Lit is just a tiny wrapper over native web components to add reactivity to their behaviour; but what is more important, Lit positions itself as a gradually disappearing library, intended to be replaced with native browser apis as they are introduced into the platform (e.g. DOM parts to help with templating, etc.). Compare this ethos to any other library out there.


"the ones that were deprecated and no browser implements anymore?"

Which spec is that?


HTML imports is a good one.

https://www.w3.org/TR/html-imports/

The v0 spec is also vastly different than how it was implemented, though I don't think it ever shipped out from behind a flag:

https://web.archive.org/web/20130608123733/http://www.w3.org...


I mean v0, I learned and experimented a lot with it and suddenly everything changed and was dropped and it was a mess. IIRC in Firefox or Chrome it shipped? At least part of them? Or I might have turned on a flag back in the day, I don't remember too much, I just know "web components are the future" and for 2-4 years they were the biggest mess I've seen with the web.


The only reason web components are alive is because Google is pouring literally millions into them.

A technology that cannot submit forms without Javascript, still can't create a submit button and whose proponents agree that it still needs 20 more standards to be generally working [1] would be dead within a year. And yet we're here in year 12 of this dumpster fire.

[1] Instead of producing a report every year, Web Component Group seems to just update the same document in place, so now it inly lists "4 standards we agreed need to be done ASAP"


From the comments I see here, it seems like many people expect the Web Components API to be a complete replacement for a JS framework. The thing is, our frameworks should start making more use of modern web APIs, so the frameworks will have to do less heavy lifting themselves, so they can become smaller, so our projects are dependent on less framework code.

Lit [0] for example is doing this. It's a very small library, making use of the Web Components APIs. Using Lit is very similar to using React. Some things work different, and you have to get used to some web component specific things, but once you get it, I think it's way more pleasant to work with than React. It feels more natural, native, less framework-specific.

For state management, I created LitState [1], a tiny library (really only 258 lines), which integrates nicely with Lit, and which makes state management between multiple components very easy. It's much easier than the Redux/flux workflows found in React.

So my experience with this is that it's much nicer to work with, and that your total project size is much smaller.

[0] https://lit.dev/

[1] https://github.com/gitaarik/lit-state


> The thing is, our frameworks should start making more use of modern web APIs, so the frameworks will have to do less heavy lifting themselves

They already do that wherever possible.

However, web componens provide almost exactly zero value to frameworks. You could ask a simple question: why did the authors of Vue, Svelte and Solid started as staunch supporters of web components (and even modeled early versions of their frameworks after them), and why are they now at best indifferent and at worst actively hostile towards web components?

> It feels more natural, native, less framework-specific.

If you ignore all the framework-specific things like custom template DSL, custom JS DSL, custom functionality like contexts and the new custom compiler, it's very native.


If you combine native WebComponents with scss and JSX/TSX, it gets even better.

As an example you could take a look at an older project on github: https://github.com/cyco/WebFun/

Here is some example code:

https://github.com/cyco/WebFun/blob/ec42d59b99d62daafea3ccce...

https://github.com/cyco/WebFun/blob/ec42d59b99d62daafea3ccce...


If a framework can support a major revision for longer than 6 months--more like 6 years--they will survive. Otherwise, the road to JavaScript madness is paved with frameworks that never learned LTS is a real thing.


There's no LTS in React but the components you wrote 10 years ago still works today in latest React. (there are some deprecations but very few)


web components are nice, but not perfect and i get tired of web component proponents neglecting to mention the trade-offs when using them.

enabling shadow DOM renders that component completely inaccessible to users using assistive tech like screen readers. without a shadow DOM enabled, you lose the encapsulation benefit devs seem to love. js framework components, for all their faults, can at least be accessible.

i just don't think web components are quite there yet.


not to mention, web components come with their own complexity around shadow tree and the question of how to style/interact within the component tree from outside etc.


You don't have to use the shadow DOM, you can use the light DOM, but then you lose slots. I think they should really prioritize using slots with the light DOM as it would make it easier to incorporate web components into existing sites.


I don’t see how light DOM slots could work since it’s just replacing element.innerHTML, but a non-style-encapsulating shadow DOM option would be great.

That, and some progress on template instantiation, reactive DOM primitives or DOM partials, so we don’t have to concatenate strings and overwrite el.shadowRoot.innerHTML, or do direct DOM manipulation for any updates.

Until that all exists, and there’s a simple API to bring it all together, other frameworks will eat this space completely.


Not mandatory to use the Shadow DOM. And you can easily add public methods to the component for external interaction.


I just got to know that svelte components can be complied into web components.

If so, then probably using svelte as a compiler for web components can be one way to do things.

Not sure about routing though. Maybe page.js or something.

Even for vanilla js, till might need vite, postcss, tailwind in some cases.


Probably not as long as there's a reason to transpile my project into minified, consolidated JavaScript, no. As long as I'm doing that, I can stick any framework I choose to into the pipe.


That's all orthogonal to web components. Like frameworks, there are some web components libraries that require a build step and some that don't.


ES modules have a problem: do they import the source code or the "binary" (minified code). As long as you're writing demos where the source code is the executable, it's fine. This is great for browser demos.

But when you start using Typescript or npm modules that export minified code, or there's a CDN involved, finding the original source for a function gets increasingly difficult, the type definitions are in a different file, and breakpoints don't work. It's almost like debugging a binary.

Compiled languages like Go do a better job of making sure you can actually read the source code, because imports always import source code.


I don't understand the problem here, or why it's JS module specific.

Source maps with pretty great, and if you're in a development setup where you say only compile out types and resolve import specifiers, they work spectacularly well, including in debuggers.


Source maps are indeed very helpful when they work, but in my experience, often they don’t for third-party modules. This seems to be an ecosystem thing. The documentation for package.json doesn’t mention sourcemaps?

According to this bug [1], even the typescript compiler’s npm doesn’t include source or sourcemaps.

[1] https://github.com/microsoft/TypeScript/issues/32207


Yeah, other than a project that was still on webpack, I can't think of any time in the last few years where this was a problem. Vite has made JavaScript apps nearly effortless for years now.


[Insert the "now you have 16 standards" joke here]


Tools and standards aren't really the same thing


Web Components is at least 10 already, and will need at least 20 more.

No, this is not a joke.


Great article. Really made me think. But don’t webcomponents lack properties and functions that can be embedded in tooling ?


In adjacent news, I love that typeface.



Is this a joke? html and css as one big JS string?


Well, yea.

All pointless frameworking is based on the fact that HTML doesn’t natively nest in other HTML or natively color in JavaScript editors. So we have ridiculous bloat, when that was all we had to fix: the ability to put HTML in JavaScript in a satisfyingly official way.

Instead, we have everything in fragments that have to be mechanically transformed, and fight over which giant IDE is best.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: