Comment by akst
2 days ago
I think it's better to think of "Web components" as "Custom Elements" they really aren't components in the way you think of components in other frameworks (which on the web introduced them first), and I think most of the dissatisfaction with them comes from trying pretend they're an alternative as they just aren't. Components in almost every other framework are efficient (efficient rendering runtime) and expressive (the ability not to have a root element but instead a frag, or context APIs etc) in ways that web components never will be, which makes them unappealing.
But when you think of them as a suite of APIs to define custom elements, that can coexist with your framework components, this delimma goes away.
I do think it's a-shame that modern frameworks don't better support shadow dom and local styles, and local events. Understandably I also get why they also don't see that as a good use of their time either, it adds complexity to the runtimes, they need to observe events at multiple root nodes.
Besides the cost of implementation and commitment to additional complexity, assuming that was a nonissue, with the exception of those otherwise legitimate reasons, there's no technical limitation that prevents React from supporting shadow roots for arbitrary custom element. I made a proof of concept of this myself seems to work quite nicely with a stylesheet loader hook (which ensured it was loaded once and there was a shared sheet between all instances of the same element), but I had to start observing events in each elements shadow root.
I think also the lack of framework support for things like defining a shadow root probably feeds into this idea it needs to be mutually exclusive.
Elements in shadow root elements can be updated more or less the same way as elements in light doms with incremental patches and updates.
The main beneficiary of supporting shadow root and local stylesheets would likely be hobbyist projects looking to minimise their build step, as local stylesheets give you much of the benefits of many of the tools that handle localising a stylesheet to a component at build time.
Unfortunately, I haven't really seen numbers on this but I can't help but I feel the way styles are bundled by most modern bundlers (with global styles and minified classNames) will likely outperform a bunch of disparate components with their own individual local stylesheet with its own request (even with http2 or whatever). So again I can see why the framework maintainers may struggle justify spending time and energy on this.
There's also the issue that web components are eager. Once it's in the DOM, and upgraded, it will cause an endless cascade of requests for every import inside.
I don't know if they fixed it, but when reddit rewrote their menu with web components, it required 100+ http requests to render.
> don't know if they fixed it, but when reddit rewrote their menu with web components, it required 100+ http requests to render.
Nothing to fix, mostly. Those are static requests and get cached.
7 replies →
I don't know I've encountered this same issue, but I've seen cases where the same stylesheet would be fetched multiple times which is quite annoying. I had to go out of my way to setup something to handle this.
Basically in my own render DSL like, I do this:
There's a bit going here, and my terrible method names probably don't help, but `ctx.useRemoteStyleSheet` internally checks if the stylesheet has been fetched is the process of being fetched, returns an object which contains the load state allowing the component to handle its unloaded state. But this might avoid that specific issue of 100+ css requests, I still get quite a few just not that many.
Before that I had a more manual process where fetches had to go through a style sheet loading "service" (or a light stateful wrapper over one). This was before I effectively made the above react like clone. Now that just happens behind the scenes, instead of all the nasty wiring I had with the web component class.
Support for anything web components-related is a death by a thousand cuts both for the browsers and for the framework authors.
For the browsers:
Shadow dom breaks almost literally everything. It's a parallel world that exists on its own and that needs dozens of additional web standards to patch holes introduced by it. And delays dozens of useful web standards that now have to be aware of it.
On top of that nothing in web components is ever created thinking even one step ahead, and break multiple pieces of basic functionality. It's a collection of barely fitting patches. E.g. at first they couldn't send data in forms. Enter FormData. Oops, still cannot be a custom form submit button. Here's a 7-year old still unresolved issue: https://github.com/WICG/webcomponents/issues/814
For frameworks:
Framework authors have to patch all thise holes on their own. Because unlike web components they actually do care about standards and browser functionality. If styles don't work, forms din't work, code doesn't work etc. because of web components, it's the framework that will be blamed.
It doesn't help that there's an insane amount of work involved in figuring out all the ways they are broken. See for example: https://xcancel.com/Rich_Harris/status/1841467510194843982#m
100% agree, and for most heavy users it really doesn't really enable them to do build any kind of app they weren't already able to do before.
The web platform has been shit long enough that frameworks and build tools ended up getting around to working around many shortcomings that shadow dom and web component APIs seek to address (such as scoping css with css modules then css in JS, now whatever else the cool kids are using), and the end result has less runtime overhead.
So say React adds support for shadow dom, as a user building a SASS app why adopt these APIs when your build system already does these? The framework authors know this, and so it's unclear what they gain from directing resources into making these parts of the frameworks API.
The only reason I tried it in my toy render DSL, is it sounded fun and unlike react I don't have to worry about breaking 10s of thousands of apps if I do it wrong.
Like I found it useful because I was trying to avoid using a build system and local styles allowed me to clean up my styles without resorting to build steps. But I'm largely building tools for myself and I don't really care about load times, and this likely isn't a representative use case.