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.
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.
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.
One fun thing I did once is use the custom elements API to make a custom tag <element-template>. When the page sees <element-template tag=what-name></element-template>, it looks inside, finds any <template></template> <script></script> and <style></style> tags, and builds a new custom element with that tag name and all the powers. Cool but not incredibly simple.
Another amazing trick is to put a mutation observer on the page to detect <template> tags as they're created. (template tags parse the HTML within but don't actually create it on the page). Once the observer finds a template tag it can upgrade them to have new powers, like replacing the contents of other tags. There are ways to tame web components and make them very easy to use.
> One fun thing I did once is use the custom elements API to make a custom tag <element-template>. When the page sees <element-template tag=what-name></element-template>, it looks inside, finds any <template></template> <script></script> and <style></style> tags, and builds a new custom element with that tag name and all the powers. Cool but not incredibly simple.
Not using it in anger in any prod system right now (finding the past, prior to AI, though), but all my side projects use it. Need to check and close any security issues this may have (not that I know of any yet. Should probably ask an LLM at some point about the danger of this).
Web Components are great for doing multi-pass rendering with template placeholder substitution happening at multiple levels in the component hierarchy. The entire element HTML hierarchy can be declared in one place. It's extremely versatile.
React cannot do this. It's difficult to explain without writing a whole essay but the benefits are very clear once you try this approach.
True, but at the same time if you're building an app the number of times when you think "I want to render this HTML without hooking it into the data store, other components on the page, data fetch layer, logging implementation, etc" is literally zero.
React can't do the thing people building apps with React never do is not an argument against React.
React is for building React apps, in case that wasn't obvious.
Seems unusual that a commit with the message "Fix broken URLs" stripped out multiple sections on performance from the FAQ [1]
- How does Elena compare against other tools? (Elena vs Lit, Elena vs Stencil, Elena vs Enhance)
- What is the performance like?
The removed sections were once so prominent they were linked from the home page, however that link was not removed along side the parts of the FAQ that were stripped so it's now broken [2].
Anyone doing anything interesting to use CSS libs like Bulma, Bootstrap with web components? Definitely feels like swimming against the tide. Got a hobby project in Lit.js, can't easily wrap (e.g.) `.btn` in a component without breaking styles because the component root/host ends up between `.btn-group` and `.btn`. One can manually add classes to the root/host but that only gets you so far. Ideally I could select when to render a root and I vaguely remember that Lit allows this but I don't remember figuring this one out.
For web components to be consumable across frameworks, you still have to write it to be compatible for different frameworks. Our platform team thought they could get away with just focusing on native js, but when it came time to use in React, many behavioral approaches were incompatible. Dealing with re-renders would clear the state of the WC, losing all dropdown items. The toggle button had an infinite re-render glitch when combined with setState. We lost the ability to require event handlers, and prod had a few P0’s over unhandled click events.
The ideal was to be close to the browser, but it’s mostly blown up in our face. The approach in this post would’ve been helpful, and it’s almost worth the cross-framework compatibility, but I just wish the entire web components standard didn’t come with an unbelievable amount of these and other problems
React had their own solution to web problems and went with it. Don't confuse that with obstinately discarding your favored technology. I personally tried web components and it was nothing but pain and solved no problems I actually had, unlike React.
The HTML + CSS first approach and JS only for enrichment sounds great, and like what should be done anyway. I wonder though, how it will play out in reality. Will web developers using this library make the effort to keep essential functionality JS free, if possible, and provide additional views using whatever web framework they use, or will they implement essential functionality as "JS enrichment", requiring JS for things that do not actually need to be done in JS at all?
In reality, building anything complex is a huge pain using web components, particularly because it is hard to author them with appropriate level of styling API and accessibility support. In my experience, web components are fantastic for consumers but terrible for the authors.
Still, the advantages are clear: they don’t need any special runtime and can be used with other JS frameworks.
Another thing in favor of web components is support for custom registries which make gradual migration from one version to another trivial. AFAIK, no JS framework has an equivalent of custom registries.
I tried to embrace web components, but when I reached "declarative shadow DOM" I really just stopped seeing the point of all that complexity just to do what I can already do with a library. The target audience of that API seems to be library developers.
I’d argue that the target audience of Web Components in general should be library developers.
Web Components are great for distributing UI elements that work with every framework.
Web Components are terrible for just building apps. Use a framework!
From this perspective, Elena seems like a welcome approach. If Web Components are for library authors, and they are, then it stands to reason that Web Component frameworks optimize for that as well.
As much as I dislike Google, Lit has been a nice middle ground for me.
It's lighter then a framework, events are vanilla JavaScript so you don't have to figure out how to make a JS libray you've found work within some framework's custom event bus.
It has enough rendering support so you don't need to update everything with .innerHTML. Change the state of a component, lit will call your render function but only update the parts of the DOM that have changed. I felt that was a nice partial answer to suggestions you need a virtual DOM because updating the real DOM is slow.
> The target audience of that API seems to be library developers.
And then most library developers find them severely lacking, riddled with unsolved and unsolvable issues, filled to the brim with invalid assumptions and awkward APIs etc :)
They are somewhat okay as framework-agnostic "leaf" components if the authors spent a lot of time honing the usage and the APIs. Things like date pickers for example.
I like web components, the simpler the better, so I like what I see but having a strong OCD about syntax I just want to propose the use of <Button ... instead of <elena-button ...
It's just a matter of using a regex [1] and making your syntax more palatable
HTML is case insensitive, so <Button> is the same as <button>, and custom element names must have a hyphen.
Your component regex represents a JSX limitation, but web components do not need React. Plus, if you capitalize the first letter, JSX would treat it as a React component rather than a web component (i.e. custom native HTML elements)
My only issue with Web Components is that, by design, they need to be registered with a globally unique tagname and can't be unregistered.
It's a reasonable compromise given the original purpose of custom elements, but in practice it ends up more maintainable to be inspired by its structures without using real custom elements despite I was initially excited that jsdom supports custom elements nowadays.
Scoped custom element registries should help with this letting you register to a shadow root instead of globally. [1] Unfortunately Firefox hasn't come to the party yet. [2]
Ok but ... why? With that I mean, why do we need it? What can be created with PWC specifically? Is there a gallery of web games? That would at the least make understanding the use case easier.
You can create anything and everything. Web components are about extending html to make it do more, progressive web components are about rendering that on the server and progressively enhancing with interactivity in the browser. Elena solves the major pain points in doing that. Components built this way can be used in any framework.
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.
9 replies →
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.
One fun thing I did once is use the custom elements API to make a custom tag <element-template>. When the page sees <element-template tag=what-name></element-template>, it looks inside, finds any <template></template> <script></script> and <style></style> tags, and builds a new custom element with that tag name and all the powers. Cool but not incredibly simple.
Another amazing trick is to put a mutation observer on the page to detect <template> tags as they're created. (template tags parse the HTML within but don't actually create it on the page). Once the observer finds a template tag it can upgrade them to have new powers, like replacing the contents of other tags. There are ways to tame web components and make them very easy to use.
> One fun thing I did once is use the custom elements API to make a custom tag <element-template>. When the page sees <element-template tag=what-name></element-template>, it looks inside, finds any <template></template> <script></script> and <style></style> tags, and builds a new custom element with that tag name and all the powers. Cool but not incredibly simple.
I went a similar way: https://github.com/lelanthran/ZjsComponent
Not using it in anger in any prod system right now (finding the past, prior to AI, though), but all my side projects use it. Need to check and close any security issues this may have (not that I know of any yet. Should probably ask an LLM at some point about the danger of this).
This article I came across last month on “Framework-agnostic design systems” happens to use this Elena library and I think explains its use case well: https://piccalil.li/blog/framework-agnostic-design-systems-p...
Web Components are great for doing multi-pass rendering with template placeholder substitution happening at multiple levels in the component hierarchy. The entire element HTML hierarchy can be declared in one place. It's extremely versatile.
React cannot do this. It's difficult to explain without writing a whole essay but the benefits are very clear once you try this approach.
True, but at the same time if you're building an app the number of times when you think "I want to render this HTML without hooking it into the data store, other components on the page, data fetch layer, logging implementation, etc" is literally zero.
React can't do the thing people building apps with React never do is not an argument against React.
React is for building React apps, in case that wasn't obvious.
Seems unusual that a commit with the message "Fix broken URLs" stripped out multiple sections on performance from the FAQ [1]
- How does Elena compare against other tools? (Elena vs Lit, Elena vs Stencil, Elena vs Enhance)
- What is the performance like?
The removed sections were once so prominent they were linked from the home page, however that link was not removed along side the parts of the FAQ that were stripped so it's now broken [2].
[1]: https://github.com/arielsalminen/elena/commit/2982c0f79ea113...
[2]: https://elenajs.com/#:~:text=Read%20how%20Elena%20compares%2...
Anyone doing anything interesting to use CSS libs like Bulma, Bootstrap with web components? Definitely feels like swimming against the tide. Got a hobby project in Lit.js, can't easily wrap (e.g.) `.btn` in a component without breaking styles because the component root/host ends up between `.btn-group` and `.btn`. One can manually add classes to the root/host but that only gets you so far. Ideally I could select when to render a root and I vaguely remember that Lit allows this but I don't remember figuring this one out.
For web components to be consumable across frameworks, you still have to write it to be compatible for different frameworks. Our platform team thought they could get away with just focusing on native js, but when it came time to use in React, many behavioral approaches were incompatible. Dealing with re-renders would clear the state of the WC, losing all dropdown items. The toggle button had an infinite re-render glitch when combined with setState. We lost the ability to require event handlers, and prod had a few P0’s over unhandled click events.
The ideal was to be close to the browser, but it’s mostly blown up in our face. The approach in this post would’ve been helpful, and it’s almost worth the cross-framework compatibility, but I just wish the entire web components standard didn’t come with an unbelievable amount of these and other problems
isn't the issue here that React & Co. don't follow standards to support web components?
React had their own solution to web problems and went with it. Don't confuse that with obstinately discarding your favored technology. I personally tried web components and it was nothing but pain and solved no problems I actually had, unlike React.
7 replies →
The HTML + CSS first approach and JS only for enrichment sounds great, and like what should be done anyway. I wonder though, how it will play out in reality. Will web developers using this library make the effort to keep essential functionality JS free, if possible, and provide additional views using whatever web framework they use, or will they implement essential functionality as "JS enrichment", requiring JS for things that do not actually need to be done in JS at all?
In reality, building anything complex is a huge pain using web components, particularly because it is hard to author them with appropriate level of styling API and accessibility support. In my experience, web components are fantastic for consumers but terrible for the authors.
Still, the advantages are clear: they don’t need any special runtime and can be used with other JS frameworks.
Another thing in favor of web components is support for custom registries which make gradual migration from one version to another trivial. AFAIK, no JS framework has an equivalent of custom registries.
Try keeping them in the light dom.
Everything works like normal html + css, but you get all the benefits of reusability and encapsulated script logic.
Lit-html (the library, not the framework) gives this approach super rendering speed too.
1 reply →
Nice! Reminds me of https://semantic-ui.com/ and its forked cousin https://fomantic-ui.com/
The syntax looks very similar to Lit, but it's a nice application of HTML & CSS first, instead of relying entirely on JS to do that.
I tried to embrace web components, but when I reached "declarative shadow DOM" I really just stopped seeing the point of all that complexity just to do what I can already do with a library. The target audience of that API seems to be library developers.
I’d argue that the target audience of Web Components in general should be library developers.
Web Components are great for distributing UI elements that work with every framework.
Web Components are terrible for just building apps. Use a framework!
From this perspective, Elena seems like a welcome approach. If Web Components are for library authors, and they are, then it stands to reason that Web Component frameworks optimize for that as well.
Yup. Lit element is much more accessible if you want “just” web components, but with a sane syntax.
As much as I dislike Google, Lit has been a nice middle ground for me.
It's lighter then a framework, events are vanilla JavaScript so you don't have to figure out how to make a JS libray you've found work within some framework's custom event bus.
It has enough rendering support so you don't need to update everything with .innerHTML. Change the state of a component, lit will call your render function but only update the parts of the DOM that have changed. I felt that was a nice partial answer to suggestions you need a virtual DOM because updating the real DOM is slow.
> The target audience of that API seems to be library developers.
And then most library developers find them severely lacking, riddled with unsolved and unsolvable issues, filled to the brim with invalid assumptions and awkward APIs etc :)
They are somewhat okay as framework-agnostic "leaf" components if the authors spent a lot of time honing the usage and the APIs. Things like date pickers for example.
I like web components, the simpler the better, so I like what I see but having a strong OCD about syntax I just want to propose the use of <Button ... instead of <elena-button ...
It's just a matter of using a regex [1] and making your syntax more palatable
Regardless, kudos for the release
* const componentRegex = /<%[ ]+([A-Z][a-zA-Z0-9])([^%]?)%>/g;
HTML is case insensitive, so <Button> is the same as <button>, and custom element names must have a hyphen.
Your component regex represents a JSX limitation, but web components do not need React. Plus, if you capitalize the first letter, JSX would treat it as a React component rather than a web component (i.e. custom native HTML elements)
I don't understand your proposal
Customer elements MUST have an hyphen.
<Button> is the same as <button> in HTML
My only issue with Web Components is that, by design, they need to be registered with a globally unique tagname and can't be unregistered.
It's a reasonable compromise given the original purpose of custom elements, but in practice it ends up more maintainable to be inspired by its structures without using real custom elements despite I was initially excited that jsdom supports custom elements nowadays.
Scoped custom element registries should help with this letting you register to a shadow root instead of globally. [1] Unfortunately Firefox hasn't come to the party yet. [2]
[1]: https://developer.mozilla.org/en-US/docs/Web/API/Web_compone...
[2]: https://bugzilla.mozilla.org/show_bug.cgi?id=1874414
Why is the uniqueness constraint of tag names a problem?
The scoped custom element registries proposal covers some of the use cases where global elements are problematic https://github.com/WICG/webcomponents/blob/gh-pages/proposal...
When you built this you probably were aware of lit. How does Elena differ from lit?
Hm, the page is unreadable on brave on dark mode.
We use webawesome.com for all our projects, it works great and is very underrated. HTMX + WA
Si by by
[flagged]
Ok but ... why? With that I mean, why do we need it? What can be created with PWC specifically? Is there a gallery of web games? That would at the least make understanding the use case easier.
It’s on the page: https://elenajs.com/#why-should-i-use-elena
You can create anything and everything. Web components are about extending html to make it do more, progressive web components are about rendering that on the server and progressively enhancing with interactivity in the browser. Elena solves the major pain points in doing that. Components built this way can be used in any framework.