re: Why I don't use web components VIEW POST


I'm sorry, but no, most of the points you defined are extracted from a bad usage of the technology. Then:

1 is not true.
You can progressive enhance web components even with js disabled.

2 is not true.
You don't have to put all the style inside the shadow dom, only the style that should not be composable or accessibile. Just like private ts functions.
You have a lot of flexibility then. I suggest to check this and define the context of your web component.

Another thing, host elements are exposed and fully customizable by external css and you should work on this. Again only the private and functional/structural css should be inside the shadow tree.

CSS-in-JS is not a problem while you write real CSS and generate it inside a css file or embedd it inside a <style> tag. The problem of the first css-in-js tools was the fact that you had to write pseudo css json-like and put it inline. Now, any modern css-in-js solution allows you write standard css and put it inside a separated file.

3 and 4 was true until 2018
Right now all the modern browsers fully support the v1 spec. This mean all the webkit and chromium based browsers (including edge). No polyfill needed for modern development, and if you have to support old browsers you're probably already using polyfill for js things so what's the problem? You just choosed a new technology to develop for old browsers.

5 is normal and it make totally sense.

Slotted elements don't live inside the shadow-tree where you put the <slot> tag, they live in the light-dom, and as any html element in light dom (for example inside the document) they are rendered immediately. Web components are custom html element, if you want to add a lazy behaviour, you have to implement it for your component, like as you do it right now with any lazyload js library.

6 This is true for the whole HTML
These issues are related to HTML and you have them with any framework if you work with plain attributes and not on top of abstractions.

Web components are not React, Vue or Svelte components, they are not logical containers, they are true html elements that live in the document and they should be used like any other html element. Taking a web component and comparing it to an abstracted svelte component is totally misleading. They do different things.

I like sveltejs and i think it's a good framework on top of good abstraction, you don't need to write falsy things about other technologies.

I'm not here to tell web components are the solution or that they are better than other tools. But i don't like content that compare two different things and claim that one is totally bad compared to the other.



This says it better than I did yesterday. Thanks.


Started here in Twitter land twitter.com/Rich_Harris/status/114..., and of course ballooned from there.


I actually don't mind the object/json style syntax so much... I use react-jss via material-ui mostly, and that generates the appropriate stylesheet and adds it to the header. I've played with abstracting it out, but including it in the JS payload works for the applications (not public sites) that I mostly work on.


Thanks for the comment. We could go back and forth for a long time saying which parts of the other's post were wrong and which were based on misunderstandings, but I'll limit myself to this: if you're saying 'this is just how it is with the DOM/HTML', then you're making my argument for me!


Rich you are on point of fact incorrect on more than half of the article's points. However if figuring this out is not your aim it would naturally lead to back and forth for a long time. Not suggesting this is your aim, or that the points could not be corrected, and in a few cases are widely held misunderstandings. Your comment to back and forth suggests a very low level of interest in actually being open to figuring out how the thing really works so you might reconsider.


If we bring the topic at this level, you have all of these problem everywhere on the web platform, independently from the tool/framework used. React, Svelte, Vue, Angular... they all work on the web platform, they work with HTML, CSS and JS and share the same platform issues. So web components too share the same issue, but they can't be compared to what you do with React or Svelte. As i wrote here web components are on a lower layer, they aren't an abstraction that generate DOM, they are HTML elements, you write real representation of the DOM (and relative issues) through new html elements, not "logical" components.

Ok, so I'm a bit confused now...

If I understood what you said correctly, then you agree on the fact that web-components are just leaky abstractions built on top of other leaky abstractions, right?

Now, what you are saying is that they can't be compared with React or Svelte, because React, Svelte, Vue... do provide non leaky APIs that "hide" the platform by treating it as an implementation detail.

So, the aim of JS Component libraries is to make "the platform" an implementation detail, because we want non broken abstractions. We want to have clean contracts that allow us to encapsulate functionality, so that we can have composable and reusable things to work with, without having to worry too much about the leaky web-platform. That's (at least in part) why JS Component libraries were created, right?

But then the platform became jealous because we were "hiding" it. So one day it came out and said:

Wait a second! I see that you like to encapsulate functionality and stuff, right? But you don't have to ignore me for doing that! Please, let me create another leaky abstraction for you... Let's call it web-components! Now, please, please, please do not compare them with those things that hide my flaws. Just accept the fact that I'm broken and that I can only produce broken stuff. Just love my new broken abstraction as it is, ok? We all have flaws...

I think that I get it now. You have more compassion for the web-platform than I do. You feel sorry for it.

I have to say that I really respect your unconditional love towards the platform! But I don't share that feeling, at all.


1 is not true.
We can't render WCs on the server and WCs not work without JS enabled. Do you ever try to create an isomorphic (universal) web app using WCs? It's the hardest part even if you work with some framework on top of this.

Also, there are many problems with forms, focus/selection, SVGs, etc.

3 and 4 was true until 2018
A problem that polyfills are not the same. One thing when you need to polyfill a simple feature or maybe transpile some new language features. But WCs polyfills always worked bad because this's a thing which hard to polyfill properly. Modern browsers are great and I really love that they're supported WCs well, but we'll never get rid of old browsers.

A simple example close to me - how often you're changing your TVs? Not so often than your phone, right? Our company working with TVs and I know that most TVs in the world (I'm talking about smart TVs of course. Today it's tricky to buy a TV without this feature) comes from 2014-16 years. There are no updates, so seems we'll live with these devices a long time.

5 is normal and it make totally sense.
It makes sense but bad DX. In Svelte 2 we had many problems with this standard behavior.

6 This is true for the whole HTML
True and it's hard to reconcile with it. HTML is really old standard and it was created in a time when no one could ever imagine how we'll use it. Constraints of HTML is the weakest part of WCs.

Writing a whole web app using WCs is too hard and even impossible nowadays. Actually, it's not a choice frameworks vs WCs. The main idea to use WCs as additional HTML elements inside of frameworks templates and it's good. We can name it leaf-components or just html tags. Btw, because of Svelte uses html-first approach, it's very simple and convenient to use WCs in Svelte apps. The main problem today is the majority of existing WCs right now depending on Polymer and it's an ecosystem.


I assure you that we will be rid of old browsers one day. People said this about IE 5 and IE 6 and when was the last time you supported IE 8?

IE is the slowest to fall out of usage, but eventually it does. Every. Single. Time.

There are plenty of real problems, no need to grasp at straws.

I believe you missed my point about TVs. If someone bought TV in 2017 he'll change it after 10 years, maybe later. So, we'll need to support it in the next 8 years. It's called never.

What? That doesn't make even the slightest bit of sense. Are you saying 10 years is "never"?

It's clearly 10 years.

I mean, 10 years ago we didn’t know what’s SPA, nor Angular, WCs was no trace yet. After 10 years WCs may not be already. 10 years is infinity for web development.

Your perspective is valid, but not complete. Look wider. In 2009 there were things like SPAs, it just wasn't as formalized and the term just wasn't coined yet.

I've been doing web development for 20 years. My career has not been two times infinity years long. If it had I'd think you'd listen to me about this. I'd be effectively God.

  • 1 You can serve both Custom Elements and built-in extends with the server
  • 3 and 4 are covered by my polyfills that work even on those TVs
  • 5 can be easily simplified
  • 6 you can have tiny abstractions on top and solve most things.

Everything is described in here:

1) Actually, I've no idea what is heresy, but I already read your article. There you show up a very simple case where whole component html representation could be rendered using just props (data-attributes). It's nice, but real cases of web app and especially isomorphic web apps are harder to implement in this way.

WCs logic can be smeared in the whole component. We can't execute WC on the server without some kind of DOM emulation or without using stuff like Headless Chrome (prerender). All these solutions work not really performant.

For example, Svelte, because it's a compiler, can calculate most of the things in buildtime and in SSR mode just concatenate the strings which are very efficient.

3, 4) Perhaps your polyfills work great, but I've used official WC polyfills by Google and it work awful.

5) Your example still too simple to agree with your ideas. Even if we leave DX to the side, in Svelte 2 we lived without scoped slots. So we couldn't bound some parent component state to the slot without proxying it through a top-level component. It was making really complicated creation of the composition of components which should work as one, like Tabs or similar, because of common logic for switching tabs should be in the parent component, but styles and hide/show logic inside each tab component. I mean markup like this:

  <Tab>Tab 1</Tab>
  <Tab>Tab 2</Tab>
  <Tab>Tab 3</Tab>
  <Panel>Tab 1 Content</Panel>
  <Panel>Tab 2 Content</Panel>
  <Panel>Tab 3 Content</Panel>

It's impossible to implement something similar in WC without manual manipulating a slot contents. Check this example: googlechromelabs.github.io/howto-c... It's a exact nightmare.

With scoped slots we can pass a part of the state of component to the child components to give a signal which tab is active now. But unfortunately, WCs doesn't support scoped slots as any other kind of communications between parent and slotted (child) components except direct DOM manipulations which are awful.

6) What do you mean tiny? Lit-html weight is 3.5Kb which is whole Preact. Lit-element already 6.8Kb. Is it still a tiny? Heresy - 8.3Kb, Haunted - 5.1Kb. All gzipped. Are we still talking about tiny abstractions or about frameworks? All these libs based on WCs, so seems most of the work already done, but why they're weighted so damn much? Things like Preact or AppRun includes whole components system but their weight comparable. All these WCs based solutions just solve WCs problems, so seems there're just tons of these problems probably.

1) heresy-ssr is the serer side isomorphic version of heresy. I've been there already with hyperHTML and viperHTML, one of the fastest Hacker News PWAs, if not the fastest, is in viperHTML
3, 4) there is no official polyfill, only one polyfill promoted more than others. The fact Google AMP project itself used my polyfill should already put an end to "the official polyfill" meme: all Custom Elements based projects that succeeded from 2014 used my poly, 'cause it's more compatible, and lighter, and it polyfills builtin extends too.
5) you don't need scoped slots to achieve that, not sure why that use case has to be complicated at all.
6) my libraries have multiple versions: fully polyfilled so no extra anything is needed, only for latest browsers, with ES5 compatible syntax, with polyfills fallbacks to vaporware (the whole ungap.github.io story).
The only reason my libraries are around 5K, but heresy wraps them with extra goodness, which nicely fits in ~2.5K, is that my libraries comes without string attached: all browsers are compatible out of the box, including old mobile, old IEs, etc.
If I could drop every single trick used to fix MS Edge or IE issues, the Safari and Firefox gotcha with Template Literals, and all other quirks I had to fix for every browser here or there, the size would be more like 3K, but then again, as long as any helper that can be used to create with ease tons of components, without ever repeating common patterns, I'm ok in shipping everything included in about 10K and call it a day: that's sill 1/6th of React, if I remember correctly, and the more browsers evolve and fix their internal issues or vanish (IE, MSEdge), the smaller and faster my libraries will become.

On top of that, my libraries requires zero tooling to work via plain standards, that means teams can use these at any time, no toolchain requirements, and I've been in enough teams in my 20 years of programming to value this part almost more than anything else.

Add simplicity, performance, and pretty much everything based on standards, except when it's more convenient doing alternatively, you have the reason my libraries are 5 to 8K, and my poly 1 to 2K. That's the entire payload to unleash all the things the Web platform could do, and beyond (see heresy-ssr, which on cold start, which is the only first time a new template is encountered, is not super slick, but after that, rendering time goes around 0.03 milliseconds, so it's pretty damn good).

1) Ok, so, how you render ShadowDOM on server-side?
3, 4) Maybe I just missed it. Could you please share a link to your polyfill?
5) Could you please describe how can I use WCs to implement these Tabs without scoped slots and manual dom querying in slotted content? I really want to enjoy your solution.
6) Seems, now I know why I not heard about heresy. I see the first release was in April. If it's good as you describe, it should become really popular. So, let's give it some time and will get in touch later to discuss it. ;-)

Code of Conduct Report abuse