Why Everyone Hates Web Components
Table of contents
- Web components promise a future of seamless interoperability, but they risk becoming the biggest threat to web development as we know it.
- Web components promise a future-proof web, but their rigid standards can stifle innovation and create dependency on outdated practices.
- Bad standards can hold us back; they shape our entire ecosystem, whether we like it or not.
- In tech, we often arrive at the same solutions because we share the same challenges; it's not copying, it's collective discovery.
- React is evolving to embrace community feedback, showing that even giants can adapt when users push back.
- Components are the future of web development because they allow for encapsulation, state management, and reusability, making complex applications easier to build and maintain.
- Understanding the difference between HTML attributes and JavaScript properties is crucial for effective web development; while HTML is limited to strings, JavaScript opens the door to a world of flexibility and composability.
- Web components promise flexibility, but their complex life cycles and event handling can create significant overhead and confusion, especially when integrating with server-side rendering.
- Web components promise flexibility but come with a hidden tax of complexity that impacts everyone in the ecosystem.
- Collaboration over conflict is the key to advancing web technology; understanding that real developers rely on frameworks transformed the Chrome team's approach and led to significant improvements.
- Innovation thrives when collaboration replaces isolation; the web's future depends on bridging gaps, not building walls.
- Web components may promise reusability, but they can end up making your app heavier and slower—sometimes, less is more.
- Web components shine in isolated, reusable scenarios, but for complex applications, React's flexibility and performance make it the smarter choice.
- Web components may be a standard, but they often compromise the developer experience, leaving us longing for better frameworks that evolve over time.
- Web components face pushback not because they lack potential, but because they need a complete rethink to match the flexibility and capability of existing frameworks.
- Web standards are essential, but they need to evolve thoughtfully; rushing to standardize without addressing real user needs can lead to frustration and inefficiency.
- Web components promise flexibility, but the reality is a frustrating struggle between general and project-specific needs, leaving developers feeling lost in a sea of complexity.
- Web components complicate development, creating a hidden tax that slows down frameworks and frustrates developers.
- Building reliable code shouldn't feel like paying a tax for every new feature; it's time to rethink our approach to web components and frameworks.
- The push for universal web components often leads to more complexity and duplication of effort, making it harder for developers to create and share truly reusable code.
- Web components have the potential to empower developers and designers alike, but until they become more accessible for everyone, their true impact will remain unrealized.
- Customization is key; owning your components leads to better solutions than relying solely on web components.
- Web components simplify the creation of project-specific elements, but complex applications will still benefit from frameworks. Let's embrace both instead of pitting them against each other.
Web components promise a future of seamless interoperability, but they risk becoming the biggest threat to web development as we know it.
Hey Theo, why are you still using React? The browser supports components; everyone should just be using web components. Well, guess what, man? There's a reason web components kind of suck. If I was the only one sitting here saying that, I'd understand why you're skeptical. But if, let's say, every framework author and relevant person in the web dev space were to say they suck, maybe you would listen to them—hopefully.
Thankfully, I'm not alone, and a lot of these really relevant people are speaking up. A while back, Rich Harris, the creator of Svelte, made a great blog post describing all of the reasons why web components don't make sense. If it was just him, there would be arguments against it, but it isn't; it's everyone. Now, Ryan Carniato, the creator of Solid and one of the most in-the-know people in the whole web dev world—one of the people I reference regularly when I want to make sure I'm getting things right—he's coming out against web components now. And if Ryan's against it, it's over.
Before we talk about the future, we need to talk about today's sponsor. Yeah, everything okay? Yeah, I'm just tired of changing providers for everything. We swapped databases three times and off-platforms twice this year. How do you keep track of everything? Oh, that's easy; I just use Appwrite. Appwrite? Yeah, they kind of just handle everything for you, from data to file uploads to authentication, so you can focus on building your app. I mean, that sounds nice, but we're building a mobile chat app in Flutter. You're in luck! Not only do they have a Flutter SDK, but they also support real-time events straight from your data. So, you're telling me I just wasted—and I'm still wasting—are you okay, man? How do I get all of these years of my life back? Thank you to Appwrite for sponsoring this video; check them out at appwrite.io.
Now, let's go through this, as well as all of the other pieces of coverage and some of the Twitter wars that have happened over Ryan once again kickstarting everyone's favorite conversation: web components and why no one actually uses them. Real quick, before we get started, though, I want to do a poll. Do you use web components? Yes, I did but stopped; no. I think that's fine for options. Yeah, we'll just do those three. I'm curious how you guys feel. We're already seeing from these numbers that it's not a popular solution, but I want to talk about just how bad they are.
Web components are not the future. A few years ago, I wrote an article suggesting that web components might not be the most beneficial direction for web development to head. This article was in 2020, so it's been over four years. There was a soft look at where they made sense and where things fell apart. It wasn't geared as an us-against-them argument, and I hoped people would come to reasonable conclusions for themselves. However, over the past few years, I've only seen the situation worsen. Some may have never taken web components seriously, but I always have. I used them in production for seven years; I wrote several polyfills in the early days for things like the Shadow DOM to use them before they even hit prime time. But my experience then and my experience since only points me to a single conclusion: web components possibly pose the biggest risk to the future of the web that I can see.
I haven't pre-read this one at all; I just saw Ryan did this article and was immediately hyped. I've been waiting for three days to actually sit down and read this. This is unusually spicy for Ryan; he's usually quite chill. I'm already getting info from chat that this is not the normal Ryan—this is pissed Ryan. This doesn't happen; I am so excited right now! Visions of Utopia! I admit that statement comes off a bit heavy-handed, but many reasons lie below the surface as to why I believe it.
It starts with understanding the proposed benefit of web components. The vision of web components is that one day, regardless of what tool you use to author them, you can have components that feel as native as DOM elements. These can be added to any website without consideration of how the website is authored—no concerns about specific build tools, specific runtime mechanisms, or the way that one would ever interface with these components would ever change. In a sense, a portable, interoperable web—one that can mitigate the future needs for migration, one that sets you up for any possible future. The perfect way to future-proof your sites and applications—compelling prospect, is it not? This is exactly why the promise of web components is so alluring and also so dangerous. Competing standards—this is one of the best XKCDs. This and the one with the single brick and the random guy maintaining it will stand the test of time; they get more real every day.
Web components promise a future-proof web, but their rigid standards can stifle innovation and create dependency on outdated practices.
Authoring web components allows for the creation of components that feel as native as DOM elements. These components can be added to any website without consideration of how the website is authored, with no concerns about specific build tools, specific runtime mechanisms, or the way that one would ever interface with these components. In a sense, this creates a portable, interoperable web that can mitigate future needs for migration, setting you up for any possible future. It is the perfect way to future-proof your sites and applications. This is indeed a compelling prospect, is it not?
However, this is exactly why the promise of web components is so alluring and also so dangerous. The existence of competing standards is a significant issue. One of the best XKCD comics illustrates this dilemma, alongside another comic featuring a single brick maintained by a random guy. These comics highlight the ongoing challenges with standards, which become more real every day.
For some context regarding this article, Ryan was arguing with people in the Solid JS Discord for days, who were trying to convince him that web components were good. He knows they're not, and this article serves as his explanation of why. It’s a fun context to have. Thank you, Dev, for the background.
The challenges with standards are evident; the more ambitious the standard, the more likely it will face opposition or alternative approaches to accomplish it. This issue does not disappear when something is standardized; it merely suggests that there is one blessed way to take it or leave it. If the sheer number of JS frameworks is any indicator, we are nowhere near reaching a consensus on how one should author components on the web. We can't even decide if you should be able to put more than one component in a file or not. It’s quite hilarious.
Even if we were a bit closer today, we were nowhere near that a decade ago. I would argue that we are further today, but a decade ago, no, React kind of invented what we consider a component. However, the ways we author it are still being debated every day. The introduction of higher-level primitives can have a positive effect; suddenly, something that was harder to do becomes easier. This initially led to more exploration, and web components caused an increase in the number of JS frameworks in the mid-2010s. It was an important inspiration for why I created Solid JS.
A similar example would be the increase in meta frameworks being built thanks to tools like V. It’s a good call-out that web components had an impact on the number of frameworks being created and on people thinking about making their own frameworks, similar to how V increased the number of full-stack frameworks being built, especially once it added the tools necessary to do that. I really like this comparison.
The difference is that V, despite having a lot of weird decisions, is generally speaking a pretty good way to build full-stack frameworks, whereas web components are not really a good way to build much of anything other than intercoms or little chat widgets. However, it can also have a negative effect; if too many assumptions are made, it becomes harder to explore alternative spaces because everything gravitates around the establishment. What is more established than a web standard that can never change?
This is also a fair point. If a web standard is wrong, they can't fix it later; they have to replace it later because old websites are promised to never break. If you build a website on web standards, it will continue to work indefinitely. That’s why something like Ladybird is so miserable to build; the size of the web standards document is absurd. I think it’s around 100,000 pages now, reflecting the crazy number of standards that exist on the web that must be implemented. This leads to the creation of weird CSS APIs, as we have to add new ones every time the old ones aren’t good enough, instead of fixing the old ones.
We can't have a new version in the same way we do with an SDK. If React wanted to change how we write components, they could make React 20 and change it. They don’t because they are honoring the promise of the web not breaking. However, you can't just break the web. The established standards are what we want to build around, but if the standard is bad, it kind of dooms everyone trying to build around it.
I’ve struggled with this a ton outside of web standards. JSX, according to the spec, has no established semantics. However, try to convince the wide range of tools out there that they are assuming too much. This is a fun call-out because JSX, which is the syntax in React that we use to write the HTML-looking stuff in our JS files, is a pretty vague standard. JSX V2 just never ended up happening or shipping, and as such, all of the JSX interpreters and tools like ESBuild and V are built with the assumption that if you’re writing JSX, you’re writing React.
Now, there are other frameworks with JSX, like Solid JS, and if Solid JS uses JSX in a way that’s...
Bad standards can hold us back; they shape our entire ecosystem, whether we like it or not.
Established standards are the thing we want to build around, but if the standard is bad, it kind of dooms everyone trying to build around it. I've struggled with this a ton outside of web standards. JSX, according to the spec, has no established semantics, but try to convince the wide range of tools out there that they are assuming too much. This is a fun call-out because JSX, which is the syntax in React that we use to write the HTML-looking stuff in our JS files, is a pretty vague standard. JSX V2 just never ended up happening or shipping, and as such, all of the JSX interpreters and tools like esbuild and V are built with the assumption that if you're writing JSX, you're writing React.
However, now there are other frameworks with JSX, like Solid JS. If Solid JS uses JSX in a way that adheres to the JSX spec but isn't necessarily aligned with the React spec, it can break a lot of these tools. I know Asan is similar when they moved to JSX as their templating language. It's an annoying challenge to work around. I can only imagine the nightmare it would have been if JSX had been standardized in the browser. Forgetting how frameworks like Inferno, Solid, and Million all work, they have done way more optimal things with their JSX transforms. Even React has changed their transformations over time.
Again, the call-out is that if JSX was part of the browser standard, no one would be able to change how it works, and all of the implementations of JSX have changed significantly over time. This is but one example of many things that can effectively tie our hands. We must tread carefully when standardizing any high-level mechanism because it assumes a lot. It is insufficient to say that not everyone has to use it when its existence inherently influences how we look at the platform in general.
I used to help Ryan a little bit with copy and wording stuff, and I want to ask him for help now. Jesus Christ, this is good! The phrase "things that help us can effectively tie our hands" is a banger quote. It is insufficient to say that not everyone has to use it when its existence influences how we look at the platform in general. I don't have a comment; he's just spitting fire, and I'm going to complain before it like he's totally right here. The web standard being bad isn't something we can just ignore; it is inherently influential. Even though we established the web component stack five years ago, we still have people every day asking about supporting them better and how to use them, even though we, as a deep community, kind of know how bad they are.
Opportunity cost is real. As a framework author, I understand this all too well. I often say that in this field, things are discovered as much as they are invented. There are so many banger single sentences in this discussion. Jesus Christ, Ryan is making my job hard! Also, I can't believe I didn't call this out before. If you're interested in what Ryan has to say, his YouTube channel is super underrated because he doesn't do videos; he just does live streams. He does them every Friday, and they are awesome. He leaves them up, and if you're looking for hours of deep-dive web content, this is one of the few channels I try to watch. I feel so bad that I've fallen behind on his streams. I used to watch him every week, and I try my best to link to his channel; it will be in the description. Please check his channel out; he deserves so much more attention than he gets on his YouTube stuff. He's the most respected person in this whole ecosystem at this point. Hit that sub button; he deserves it! Notice that I have the bell on for him. I have the bell on for like three people.
So, yeah, if you like what he has to say here, if you like what he's doing, go give him a sub and watch his streams on Friday; they're insane. Back to the article, I often say that in this field, things are discovered as much as they're invented. What I mean by that is there's a certain truth or physics, if you will, to design decisions that, when followed, will lead us all to similar places. I have an example of that in my TanStack start video I just published. How do I put it? I made a proposal a long time ago for an example of how I thought server functions could work with React Query to compile out like RPC functions effectively.
What I learned after that is my design for that was kind of annoying to implement, at the very least. But also, TRPC existed, so I went into that. Now, four-ish years later, everyone's implementing nearly identical to the thing that I wrote. I'm not saying that I was super ahead and invented this thing and they all copied me; I'm saying we all came to the same conclusion over time. That happens when you look at the way technology works, and you're deep enough in the space; we all see the same patterns emerge.
In tech, we often arrive at the same solutions because we share the same challenges; it's not copying, it's collective discovery.
Decisions that, when followed, will lead us all to similar places. I have an example of that in my tan stack start video I just published. How do I put it? I made a proposal a long time ago for an example of how I thought server functions could work with React Query to compile out like RPC functions effectively. What I learned after that is that my design for that was kind of annoying to implement, at the very least. But also, tRPC existed, so I went into that. Now, four-ish years later, everyone's implementing nearly identical solutions to the thing that I wrote. I'm not saying that I was super ahead and invented this thing and they all copied me; I'm saying we all came to the same conclusion over time.
This phenomenon happens often. When you look at the way technology works and you're deep enough in the space, we all see the same flaws, and those will often bring us to the same solutions. It's a really important call-out here. It isn't that these tools copy each other blatantly; they fall into the grooves. I absolutely agree, and it sucks when people accuse others of copying when we're all just falling into and discovering the same things for the same reasons. Once a discovery is made that changes our outlook, the damage is done before we write a single line of code. If your job is to design a system, you don't want redundant parts; you want clear and purposeful boundaries. Instead of making a million variations on the same thing, you try to reuse one thing more. Recognizing that to accomplish common tasks, you need multiple things; these pieces become intertwined.
I was about to bring up React as an example. I'm curious how it does it, though. For example, React developers definitely felt how long it was between the announcement of Suspense in 2017 and when we finally got a data fetching story for Server Components in 2022. Why did this take five years? Because it wasn't a straight line. It took a while to understand how all the pieces fit. That, in itself, is reasonable, but more importantly, React didn't want to release its piecewise until they knew they had an answer for the whole story.
The reason that some of these releases take so long is because React was scared of releasing things that weren't complete. We've even seen that, funny enough, with Suspense. They changed the way that multiple components under Suspense work. If you're curious, watch my Suspense drama video. We put way too much time into that one little subtle detail of how these things work, as they are enough to break whole workflows. So, they go out of their way to make sure that the whole thing fits together before it goes public. As they looked more and more, all these pieces were related, and while they could be broken up, they needed each other to paint the whole picture.
Server components do not fit everyone's idea of how data fetching with Suspense should work in React. Maybe people could have benefited from a client-side data fetching primitive. React chose to be ambitious here, which is their right as a tool, and they decided what was best. However, this could have played out in a number of ways. As a developer, I can always choose not to use React, and while I can choose not to use certain React features, it is clear that everything in React has shifted to their current mental model. I might even be wishing I could easily migrate off React.
Okay, this is interesting because it seems like the React team is going in a slightly different direction right now. Let me find it: Server Actions just got renamed to Server Functions. Previously, Server Actions, as implemented in Next.js, were post functions you could fire off of forms or on clicks that could only be done sequentially. You couldn't have them in parallel, so using them for data fetching was dumb—really dumb. Changing it to Server Functions was scary for me because now people are going to use it to fetch data in JSX, which means on the client, after something loads, you can fetch data using them. You could before, but it was awful because of the sequential nature of them.
I was terrified that renaming it to Server Functions would encourage that behavior even more, which I considered anti-patterns. I went as far as to get the Next.js docs updated to remove the call-out in the Server Action section that you could use them to render HTMX and pass data to the client because it was misleading to so many people. But when I called out that I don't like this change for that reason, I got replies from the team that were really relevant. They called out that unless they're swapping over to making it so you can do queries from Server Actions instead of only using them to post, it seems like an odd change. Server Functions feel like they imply it can be used for more than just mutations. This is definitely happening, and then Jim, who is the one in charge of the Next.js team, called out...
React is evolving to embrace community feedback, showing that even giants can adapt when users push back.
I am terrified that renaming it to server functions would encourage that behavior even more, which I consider anti-patterns. I went as far as getting the Next.js docs updated to remove the callout in the server action section that you could use them to render HTMX and pass data to the client because it was misleading so many people. However, when I called out that I don't like this change for that reason, I received replies from the team that were really relevant.
They pointed out that unless they're swapping over to making it so you can do queries from server actions instead of only using them to post, it seems like an odd change. Server functions feel like they imply they can be used for more than just mutations. This is definitely happening. Jim, who is in charge of the Next.js team, mentioned that there will be explicit new APIs. Ricky chimed in when I said that using server actions for fetching JSX was misuse, clearly implying that the intent here is to enable the new primitives in React to be used for things on the client side to get data from the server.
While yes, the direction React was pushing and the mental model they were advocating for was very much server first, with server rendering as the method of updating content on the page, it does seem like they’re caving a little bit and allowing for client data fetching primitives. To the point here, you can always choose to not use certain React features. It's clear they’ve shifted their mental model, and I would argue this is due to the pushback. React is willing to adjust their mental model to encompass more of the community, and they are willing to take steps back and make changes based on what resonates with the community. The fact that people were wishing they could migrate off React is part of why they’re doing that.
That all said, the thing I'm talking about happened after this article, and I bet the author would have written this paragraph differently if the order of events had been different. There’s a big difference here: React is a library and isn’t a standard. Those options aren’t the same when it comes to standards. If all I wanted was scoped styles and now I have to deal with the shadow DOM because that was the abstraction that best fit with having a single way to do things due to web components, well, that’s what I’m stuck with.
When primitives overstep their desired usage and over-abstract, you don’t get to come back from that. You’ve already paid the cost. As anyone who has done major architectural refactoring can attest, the hardest part is adjusting boundaries. If things fall under the same logical grouping, they are easier to update. It is when you need to break things apart that it gets truly challenging. You can always add another layer of abstraction to solve a problem, but removing one can be difficult.
Somebody called out that this article feels like it’s falling into the comparing web components to React pitfall. I don’t agree with that right now at all. The only thing he’s called out so far about web components specifically is that if you’re trying to use scoped styles, bringing in the shadow DOM is the only way to use scoped styles because web components are limited. Everything else is just the framing of why standards are important. He’s not comparing anything to React so far, at least not the goal of the solution, but we’ll see if that changes as we go forward.
It is worth noting that a big portion of why web components exist is because of people on the Chrome team at the time, particularly a certain Alex Russell, who was not fond of React. Their goal was to make it irrelevant. They’ve since changed their goal, and I’ll talk a little bit about that later. However, web components were built as a standard as a response to React, not as a replacement for React or as a similar mental model to React, but as a response to it.
The fundamental problem with web components is that they’re built on custom elements. Elements are not components; more specifically, elements are a subset of components. One could argue that every element could be a component, but not all components are elements. This means that every interface needs to go through the DOM in well-defined ways that aren’t a perfect fit, and some in newly defined ways that augment or change how one would deal with elements to accommodate extended functionality. I’m curious where he goes from here; I have a lot of thoughts, but thus far, he has covered everything I wanted to say.
Components are the future of web development because they allow for encapsulation, state management, and reusability, making complex applications easier to build and maintain.
Standard as a response to React is not intended as a replacement for React, nor is it meant to serve as a similar mental model to React, but rather as a response to it. This leads us to consider the cost of abstraction. The fundamental problem with web components is that they are built on custom elements. It is important to note that elements are not components; more specifically, elements are a subset of components. One could argue that every element could be a component, but not all components are elements.
What this means is that every interface needs to go through the DOM in some well-defined ways that aren't a perfect fit, and in some newly defined ways that augment or change how one would deal with elements to accommodate extended functionality. I am curious where this discussion goes, as I have a lot of thoughts, but thus far, everything covered has aligned with what I wanted to express.
To iterate on what is being said here, an important thing to understand about elements versus components is that an element is meant to be a dumb piece, like a div, button, or paragraph. Web components are appealing because they allow you to write your own custom-based elements, and you can even do things like pass HTML, as that is how elements work. However, the idea of an element inherently containing its own things—like if I wanted to have a labeled button with "edit" that I could reuse in three places—means that it is no longer just an element. This is because it doesn't have the same primitives; an HTML element is the base primitive and doesn't have sub-elements unless you declare them.
A component, on the other hand, not only has sub-elements but also has the ability to pass elements of different types. For example, in React, I could have a prop here, such as SuComponent
, which could be a React.Element
. Now, I can pass this app component some component and render it. If I go to the main and pass sumComponent
as a div, it just works. This idea of properties that you can pass, along with state that you can own, is an important part of components. Elements don't inherently have state beyond form data that is baked into them, which is minimal and part of the browser's functionality. Even then, the expectation is that you're controlling that with JavaScript.
The concept of intertwining state, behaviors, styles, and markup as one box is what defines a component. I haven't even really delved into styles here, but the idea that you could write style code that only affects this component and doesn't impact others is also significant. I have been using React long enough to remember times before we were deep into things like Tailwind, where you would put class names here, still have a CSS file, and things would break all the time because you accidentally used the same class name in two places. All of these experiences were part of the development process.
As we have improved at encapsulating our components so they live in isolated boxes, building large applications with many developers has become significantly easier. Components won for a reason; this model allows you to write things that are simple simply and write things that are complex maintainable. This unique aspect of components is part of why they work so well. The primitives they use are either other components or elements, and having those as the base properties that we assemble components with is a huge part of their power.
Web components, by design, are trying to blur the line between an element and a component, and this creates complications. Returning to the article, what it means is that every interface needs to go through the DOM in well-defined ways that aren't a perfect fit, and in newly defined ways that augment or change how one would deal with elements to accommodate for extended functionality.
To begin, DOM elements have attributes and properties so that they can be represented as HTML attributes, which accept only strings. In contrast, properties being a JavaScript interface can handle any value. This is a really good call-out; when you're passing things in traditional HTML, you can only pass strings. However, when you're using JavaScript and something like SX or any other web framework with components, you can pass things like markup or even another component. For instance, I could create a quick counter button and pass it here, and it will just work—that's so cool!
Unfortunately, web components do not allow for this type of composability, making it basically impossible because they expect everything to be a string. Native DOM elements have many rules around specific attributes and properties, such as how some are booleans—where existence means that they apply—while others are pseudo-booleans.
Understanding the difference between HTML attributes and JavaScript properties is crucial for effective web development; while HTML is limited to strings, JavaScript opens the door to a world of flexibility and composability.
HTML attributes accept only strings, while properties, being a JavaScript interface, can handle any value. This distinction is important when you're passing things in. In traditional HTML, you can only pass strings, but when you're using JavaScript and something like SX or any other web framework with components, you can pass things like markup or even another component. For example, I could create a quick counter button and pass it here, and it would just work. That's so cool! However, web components do not allow you to do these things; they make that type of composability basically impossible because they expect everything to be a string.
Native DOM elements have many rules around specific attributes and properties. For instance, some are booleans, where existence means that they apply, while others are pseudo-booleans that require an explicit true or false. This inconsistency can be frustrating. When web standards change, it's often too late to adapt. Some properties reflect to attributes, while others do not. A goal of templating languages is to solve this in a uniform way. We can create special rules around known elements and attributes, but with custom elements, we lack that knowledge. This is why some templating libraries have interesting prefixes to indicate how things should be set. Even Solid JSX has prefixes like attribute:
, prop:
, and buon:
for this reason. Consequently, every runtime location and compiler hook needs to be aware of these distinctions.
To clarify, this is a really important point that took a moment for me to grasp. Even native DOM elements have many peculiar ways to interface with them. For example, if I have a button and I want it to be disabled, I can simply write disabled
. However, if I want to use aria-disabled
, I must explicitly pass it as true. Even though both are disabled flags, one can be passed without a value, while the other requires a string value of true or false. This is just how HTML works, and while it may seem terrible, we have managed to work around it because every framework and tool built around the web adheres to a standards document that defines the behavior of each element.
This situation is annoying, but the community has adapted because we have a standard that we all agree on. Even though the standard means that different elements exhibit different behaviors, we can build around it in a consistent manner. However, when creating our own elements, as described here, we face uncertainty regarding how these attributes will behave. We don’t know if they will be treated as booleans, if they are attributes, or if they are properties. Therefore, to make this work—especially when trying to mount a web component in another framework like React or Solid—you now have to manually declare all of these things for every single element type. That’s quite cumbersome.
Someone in the chat asked if I just said semantic HTML is annoying. I want to clarify that semantic HTML refers to the meaningful use of HTML elements, while the differences in how you pass these two things through are not about semantic HTML; they are about bad design that is now too late to fix. The distinction is crucial. When you add new elements indiscriminately using things like web components, you are bound to encounter problems. Solid has had to address these issues with peculiar prefixes, which is less than ideal.
I apologize for any confusion regarding the term "attribute," as I sometimes rotate between saying "attribute" and "attribute" due to my accent. This has led to enough comments that I find it amusing to switch between the two. You might be thinking that we need better templating as a standard, but, like JSX, we must consider the implications of that decision. A few years ago, most people would have likely agreed that the way something like L HTML rendered templates was a good approach. Other solutions could output it as well; however, we have since realized that reactive rendering, like what Solid does, outperforms it. It achieves this by changing the semantics of the templating process.
If we had proceeded with the way Lit was doing things, we would have ended up with a standard that isn't the best method for templating. This is a fair point; the early proposals and the way Lit was functioning might have seemed promising at the time, but we have learned a great deal since then. Now, we find ourselves in the midst of the signals wave, thanks to Solid JS proving how powerful and performant it can be.
Moreover, DOM elements can be cloned, but custom elements exhibit different behaviors, which means they should be imported instead. They have DOM-based life cycles that can trigger either synchronously or asynchronously, depending on the context.
Web components promise flexibility, but their complex life cycles and event handling can create significant overhead and confusion, especially when integrating with server-side rendering.
In the ongoing discussion about web components and templating, it becomes clear that reactive rendering, like what Solid does, outperforms traditional methods. This performance advantage stems from changing the semantics of the templating. If we had proceeded with the approach that Lit was using, we would have established a standard that isn't the best way to do templating.
It's important to note that while the early proposals and the methodologies of frameworks like Lit may have seemed promising at the time, we have learned significantly since then. Currently, we find ourselves in the midst of the signals wave, largely due to Solid JS demonstrating how powerful and performant these solutions can be. However, the challenges don't stop there.
DOM elements can be cloned, but custom elements exhibit different behaviors, necessitating their import instead. Custom elements possess DOM-based life cycles that can trigger either synchronously or asynchronously, depending on when they upgrade. This complexity wreaks havoc on aspects like reactivity tracking and context APIs. The peculiarities of these DOM life cycles can be quite frustrating.
For instance, if you have a web component with its own life cycle that has been mounted by Solid, which also has its own life cycle, you must create a bridge between these two distinct ways of managing components and life cycles. This situation can be quite challenging. However, these details are crucial for interfacing with native DOM behaviors and events.
Moreover, there are other quirks to consider, such as the behavior of event targets in the shadow DOM. Certain events do not compose; they don't bubble beyond the shadow DOM boundaries. Additionally, some events may not bubble consistently due to the shadow host always being the target, regardless of which child element gains focus. This can be quite problematic, especially when trying to manage focus within web components.
To clarify, the focus elements on a web component do not direct focus to the child element that gained it; instead, they focus on the entire element itself. This limitation is particularly cumbersome when attempting to nest web components within one another. While we could discuss these issues for days, it’s essential to recognize that some challenges arise from today's shortcomings, while others are by design. The commonality is that they all require specific considerations that would otherwise be unnecessary.
Of course, this complexity comes with a performance overhead. Ryan has written extensively about performance in web components, addressing many of these concerns meaningfully. It's worth noting that if an event is viewed from a handler inside the shadow DOM, the target is accurate. However, if viewed from a handler outside, it becomes opaque as to which element within the shadow DOM was targeted. This inconsistency is frustrating, but there are workarounds available.
Even if we consider the performance costs to be minimal, we must question where this leaves us when it comes to server-side rendering (SSR). Yes, it is entirely possible to implement SSR with web components, and hydration is completely achievable. This was not always the case; previously, web components did not support server-side rendering, leading to various hacks to make it feasible.
The crux of the issue lies in the fact that there is a DOM interface in a place where there is no DOM. The browser has a DOM, which is how server components were designed to interact with the real DOM and the shadow DOM. However, on the server, the environment lacks a DOM. Most server-rendered frameworks operate by outputting a string that gets rendered in the browser and then hydrated with JavaScript on the other side.
You can create a minimal wrapper to manage most of these issues, but this introduces extra overhead. This complexity arises from our attempts to make components behave like something they are not on the server. There is no universal standard for this, leading us back to having specific solutions. Ultimately, this situation resembles just another type of framework, offering no more guarantees than if one were to choose Vue or React for a new project.
This observation is crucial; if the goal of web components is to establish standards, we must make informed decisions regarding their implementation. To effectively use web components, some form of framework is necessary, especially when considering server-side rendering.
Web components promise flexibility but come with a hidden tax of complexity that impacts everyone in the ecosystem.
Rendered frameworks work in a way that they spit out a string, which then gets rendered in the browser and subsequently hydrated on the JavaScript side. You can create a minimal wrapper to handle most things, but this introduces extra overhead. This complexity arises all because we tried to make components something that they aren't. On the server, there is no such standard; we are back to having specific solutions. It is just another type of framework with no more guarantees than if I choose Vue or React for my next project. There is nothing wrong with that; we need to recognize that fact.
That's a fair point. If you're doing this on the server, and if the goal of web components is to be the standards, you have to make decisions around these things. To use web components, you must employ some form of framework around them, especially if you're also server-rendering. It sucks. The real cost of web components is significant. I just saw a message from Ryan saying that he is on vacation and went on vacation right after posting this. He wanted to apologize for not being part of the discourse after making the blog post. So, thank you, Ryan; no hard feelings. You're not missing out on much; everybody's just lamenting how right you are.
If you're wondering why Ryan's not in chat and why he hasn't said anything after this, he's on vacation. Let him have a good vacation; he deserves it. The complete picture is one where the complexity of dealing with native elements increases to account for the newfound flexibility of web components. It is something that tools support better. Not only is the user of them paying the price, but all of the users of the tool are facing more code to ship and more code to execute to check these edge cases. This is a hidden tax that impacts everyone.
This is another good call-out because I think a lot of the people who like web components aren't framework authors; they are using them for very small cases or medium-sized applications. Every framework author understands how bad this is—like all of them. I think every framework author, except the React team, went through this phase. I certainly did. Some of Felt's worse design flaws are the direct result of us planning for a world in which web components were the dominant compile target. I believe Evan did, and Ryan in particular went very deep on them. Of course, we would; we're all super competitive with each other. If we could offload the work to a platform primitive that results in better performance and smaller bundles, then we would be all over it.
In a sane world, the fact that we, of all people, are the least enthusiastic about them would prompt some deep introspection from the people designing these specs. Instead, we get admonished for not contributing to hand-waving to make them better, or we get subtweeted about conflicts of interest and other inane issues. You see, it's a conflict of interest to maintain a framework, even though web components don't compete with frameworks. However, there is no conflict of interest involved in being paid to work on web component frameworks, specs, or component libraries. Meanwhile, we are always 20 specs away from parity with userland, and the complexity of the very platform keeps compounding. It's absolute madness.
Oh, and he mentioned that other than React, Ricky came in; React also went through this phase. The conclusion that everyone else came to was pretty quick, so it might look like it was skipped from the outside. Also, Sam called out that Ember tried and gave up because of this. The context is that every framework author tried because we all wanted to support the browsers. This is a great point: they don't know how awesome web components are. Well, we spent years trying, and they don't work; they suck. There were people from the Angular team commenting on this too. Evan had a rant about it; everyone's been calling this out.
I want to shout out one of my favorite people in this ecosystem, Nicole Sullivan. Nicole was one of the leads on the Google Chrome team. When she joined, she saw how much tension there was between the Chrome team and framework authors. So, she went out of her way to try and bridge this gap and better understand the situation. The first thing she did was find a ton of data; she went and scoured the web to see what websites were using what technologies. Nicole had an awesome fireside chat at Reactathon last year that I've been thinking about since I heard it. I want to take this opportunity to share parts of it; link in the description if you want the whole thing. The whole thing is worth it.
Okay, so the context here is that Nicole was asked about what benefits they've seen since they started collaborating with the React team and other framework teams more, and her answer here is really valuable for understanding how we got to the place we're in today.
Collaboration over conflict is the key to advancing web technology; understanding that real developers rely on frameworks transformed the Chrome team's approach and led to significant improvements.
When Nicole joined the Chrome team, she observed a significant amount of tension between the Chrome team and framework authors. In response, she made a concerted effort to bridge this gap and better understand the situation. The first step she took was to gather extensive data; she scoured the web to determine what technologies various websites were utilizing.
Nicole had an awesome fireside chat at Reactathon last year that has been on my mind ever since I heard it, and I want to take this opportunity to share parts of it. For those interested, a link to the full chat is in the description, and I assure you, the whole thing is worth it.
In the context of her discussion, Nicole was asked about the benefits they had observed since they began collaborating with the React team and other framework teams. Her answer is particularly valuable for understanding how we arrived at our current situation. She stated, “I don’t think it’s hard to even put into words how much it changed things.” When she joined Chrome, there was a sense of an adversarial relationship with frameworks. This sentiment was puzzling to her, as she believed that they should be on the same team, given that they shared the same goals for the web.
Nicole explained that a significant part of their organizational strategy now focuses on how to meet the needs of abstractions, tools, and frameworks. They conducted a study to analyze the developers using vanilla JavaScript and discovered that these individuals were often working alone or with just one other person. Furthermore, they were likely not utilizing any other tools, such as npm or the standard set of tools that many developers have come to rely on. From this, Nicole concluded that these developers were likely hobbyists or students, which allowed the Chrome team to shift their perspective. They recognized that the bulk of the web uses frameworks, cares about frameworks, and wants their frameworks to be good and fast.
Nicole praised the React team for their collaboration, stating that they were amazing and worked closely with the Chrome team even when they had little understanding of the technical aspects, such as hydration. Their willingness to educate and assist was crucial in helping the Chrome team create useful browser features and contribute to performance improvements.
Reflecting on this, I often think about Nicole's insights and the significance of this collaboration. At the time she joined, there was an adversarial relationship between Chrome and framework authors. However, it became clear that real developers were using frameworks, while those building with vanilla browser standards were primarily hobbyists. For the web to continue improving and to enhance the online experiences we expect, it was essential for the Chrome team to support the framework teams.
Nicole's experience illustrates the challenges faced during the peak of the anti-framework era, when the Chrome team did not fully understand or appreciate frameworks, leading to conflicts. This historical context sheds light on why web components were created during that time and highlights the disdain that existed between the two.
To be frank, this situation likely contributed to Nicole's current position at Apple. Her ability to navigate these political challenges and advocate for the right course of action is remarkable. The conversations I had with her were among my favorites, and I would love to bring her on for a discussion. By the way, Nicole, you have an open invite if Apple will allow it; I just don’t want to get you in trouble with your job.
Nicole has done more for the web than many others, working tirelessly to undo the damage caused by the old culture. I wanted to emphasize her contributions because they are incredibly important. I highly recommend watching the entire chat; it is filled with valuable insights. The link will be in the description. Thank you, Nicole, for your hard work, for recognizing the importance of frameworks, and for beginning to rectify the issues surrounding web components. I felt compelled to share this perspective.
Innovation thrives when collaboration replaces isolation; the web's future depends on bridging gaps, not building walls.
To do the right thing is unreal, and the conversations I had with her were some of my favorites. I wanted to bring her on, and by the way, Nicole, you still have an open invite if Apple will let you. I just don't want to get you in trouble with your job. She's just one of those people that has done more for the web than almost any other group, and she's worked so hard to undo the damage of that old culture. I wanted to call that out because I think it's really important. Honestly, I highly recommend watching this whole thing; it is full of bangers. That link will be in the description. Thank you, Nicole, for the hard work you've done. Thank you for recognizing that we use Frameworks for a reason, and thank you for starting to undo the damage of web components.
I wanted to go on that rant quickly because there's a reason all the framework authors have this problem, and it's not because of skill issues. It's because of that weird tension between the two. All the comments from chat here are brutal. I can imagine Hacker News losing their minds over this. They really believed everyone wants to use vanilla JS and HTML. Yep, someone should just write a blog post based on that talk and post it on Hacker News because video posts don't do well there anyway.
Now, back to the article. For those who have stuck around, I know this is a long video, but we have to get to Leah's response. I’m sure this will be really good. I have massive respect for Leah; she's changed my opinion on things many times, so I'm very excited to read that. Make sure you stick through to the end, as we will get to that too.
Anyways, I've talked about where early standardization would have been catastrophic, but it also has the potential to stifle future innovation along certain paths because it assumes too much. Improvements to hydration, things like resumability and partial or selective hydration, depend on event delegation to work. However, if the Shadow DOM messes with that, then how could web components fit the model? Some might say that SSR was an oversight because we didn't think about that much in 2013, but the gap only continues to grow over time.
One of the things that most modern frameworks do is allow you to generate the HTML on the server so you can load that before the JavaScript has started. The JavaScript starts and takes over the page; that's what hydration is. You get the HTML first, and then the JS comes in. For example, a button might have rendered on the server, so when you click it, it doesn't do anything. The JavaScript comes in, re-renders the button in order to attach to it, and now when you click it, it works.
Most frameworks are smart enough to have a little bit of JavaScript running that keeps track of anything that gets clicked while all of the other JavaScript is loading. This allows it to make a queue of these events that occurred before the JS loaded, and then it can replay them once the hydration happens. But, as mentioned before, with the weird targeting of Shadow DOM elements, you can't watch and replay events that occur inside of a web component.
For instance, if I have a web component that's like a counter button and I click it, I get the events that the shadow component was clicked. However, I can't hydrate those into the web component after the fact to actually trigger those events because the web component is isolated at a really weird spot. So even if you server-render it, it breaks all of these types of behaviors that, to be fair, took framework authors years to figure out. Since web components were built as a reaction to frameworks instead of in collaboration with them, they missed all of these learnings. Now, we're reinventing all of them, and all of the complexity, all of the weird decision-making, and all of the workarounds for building with frameworks have to be done around web components to make them work.
So, you're not just picking web components or a framework; you're picking web components and a weird framework built around their madness or a framework that already has their madness figured out. For those curious, I just did a video on yield—that's an example of one of the APIs that was designed in collaboration with the React team to make it so all frameworks can do more.
I have this one tweet I wanted to highlight because I thought it was really funny. I put it in the video: "I had to Google what web components were, and when I first looked at the source code, I knew I'd entered the ninth level of hell and quickly closed the tab. I've seen those demons before—no sir, hell no! I don't even want to put you guys through looking at that syntax, so I'm not going to put it in the video. But if you want to see why people are so upset, go look up some example server components.
Web components may promise reusability, but they can end up making your app heavier and slower—sometimes, less is more.
In the discussion surrounding web components and their integration with various frameworks, there is a notable contrast between the approaches taken by different technologies. Some frameworks have successfully addressed server-side rendering (SSR) challenges, while web components, being a browser standard, lack inherent support for SSR. This limitation means that the responsibility of adapting web components for server-side use falls on the community, which can be quite cumbersome. As a result, the notion of web components as a superior standard has shifted; they are now viewed primarily as a developer experience consideration that disappears from the final output to optimize user experience.
Ryan's perspective on components highlights that they can often be pure overhead, suggesting that components may slow down applications once compiled. The idea presented in a recent blog post argues that components serve merely as developer tools that do not contribute to performance, and ideally, they could be entirely compiled out. However, with the establishment of web components as a standard, the inefficiencies and overhead associated with components have become ingrained in the browser itself. While innovative solutions may emerge, they often come with hidden costs due to foundational misalignments and the wrong abstractions.
The dialogue surrounding these issues is complex, as different solutions come with various trade-offs. For instance, web components might only succeed with the backing of standards bodies due to their need for pervasive support. This raises the question of whether the current ideal is truly achievable. The discussion often parallels debates about micro frontends or microservices, where organizational alignment with developers is beneficial. This concept is encapsulated in Conway's Law, which posits that organizations are constrained to produce designs that mirror their communication structures. Thus, the way teams are structured directly influences the architecture of the software they produce.
The isolation and reportability offered by web components allow for the integration of multiple components from different sources on a single page. However, similar to the caution against using various programming languages for microservices, there is a reluctance to mix different frameworks for components. The front-end landscape is particularly sensitive to the cost of each kilobyte of JavaScript, making maintenance and payload reduction critical considerations.
A significant point of contention arises with web components, as their isolation can hinder reusability. For example, if one were to use 15 React components alongside 15 web components, the total weight of the web component implementation could exceed that of the React alternative. This raises concerns about efficiency, especially in scenarios where a minimal HTML page—like a blog—requires just one dynamic element. In such cases, introducing React may seem excessive when web components can provide a compelling solution for reusable interactive elements in an otherwise static application. For instance, if a blog needs a comment section or a like button, the choice between web components and React becomes a practical consideration.
Web components shine in isolated, reusable scenarios, but for complex applications, React's flexibility and performance make it the smarter choice.
The discussion around reusability between web components and React highlights some important considerations for developers. While a web component could theoretically be a few kilobytes smaller than its React alternative, the overall size of a site can increase significantly. For instance, if you have 15 components in React and 15 web components, the web component site starts to weigh more. This is particularly relevant when considering a super minimal HTML page, like a blog, where you want to have one dynamic element reused in multiple places. In such cases, we shouldn't have to introduce React to our code base to achieve that. Web components present a compelling way to have single reusable pieces of interactivity on an otherwise static application.
For example, if you have a blog and want a comment section or a like button, web components probably look pretty good. However, if you're building an interactive application, the choice between using web components and React becomes more complex. With web components, you may face limitations such as the inability to compose them, mount them inside one another, or hydrate them after the fact. In contrast, React addresses all these problems effectively. Therefore, React is actually the better solution, not just the preferred one. Technically speaking, React will run better, work better, and provide significantly better maintenance for the project. The size of the JavaScript bundle will also be smaller, as all these aspects are optimized in React. When one framework is running your web page and application, reusability becomes much easier.
On the other hand, the reusability and composability of web components, as individual boxed pieces, do not scale across your application. They are the most reusable part, but you cannot interact with or compose them in the same way you can with React. With React, you gain all of this flexibility along with a smaller payload size since you are only loading React once. If your goal is to future-proof your application, you need to be prepared to maintain different versions of even the same library on the same page. This holds true for both Lit and React. You could choose to never update anything, but that option exists without web components as well. There are no additional guarantees for future-proofing here; the only choice is to freeze things, maintain multiple versions, and load more JavaScript on your page.
Realistically, you will update your libraries in lockstep, which is also the case with any library. If you only have a single library on your page, web components aren't doing anything for you but adding more overhead and possibly interfering with features that the library provides now and in the future. In such scenarios, you might as well use the library without web components.
The second consideration is granularity. If you're working with micro frontends, that represents a contained swappable piece. If you decide in the future that it's not the best way to handle things, you can swap it out. However, once you adopt web components everywhere, you will need to address each of these touchpoints. Web components differ from micro frontends and microservices because they can be used cross-sectionally. This is good for standardization, but it's worth noting that I have never seen a company completely eliminate jQuery once it has been adopted.
If you have one component that uses a specific library or tool, and you have this web component or micro frontend in your application, you will never fully get rid of it. For instance, I recall the old Rails and Ember code base at Twitch that I helped move us off of in 2018; it still has some pages being served, which is quite surprising. The most compelling uses for web components are as a sort of micro frontend, where the scaling costs are minimal, and outside communication is limited.
A great example of this is the little chat widget that many websites use, like Intercom. This chat app allows every developer in any framework to mount this chat feature on their site easily. You don't have to adjust it to fit a specific framework, and it doesn't require extensive communication with your page. Thus, it works well for that purpose. Outside of such specific use cases, however, there are not many scenarios where web components make sense. As mentioned, they are often a one-off solution, and in those cases, the friction is low enough that having web components isn't necessary.
In conclusion, I would prefer to use web components for their ergonomics, as exemplified by Zenex W. It is essentially the same concept as the Intercom chat widget, which is quite amusing.
Web components may be a standard, but they often compromise the developer experience, leaving us longing for better frameworks that evolve over time.
In the realm of web development, the chat app is a common feature that many sites implement. It typically includes the little chat button that allows users to communicate directly with the service provider. This feature serves as a great example of a web component, as it enables developers across various frameworks to easily integrate this chat functionality into their sites without significant adjustments. The chat component operates independently, meaning that my page doesn't care what's going on in Intercom, which contributes to its effectiveness.
However, outside of this specific use case, there are not very many use cases for web components that make sense. As previously mentioned, the chat widget is often a one-off scenario, and in such instances, the friction is low enough that the necessity of web components is questionable. While I appreciate the ergonomics of using web components, I find it amusing that Zenex W was mentioned as being essentially the same as the Intercom chat feature. This similarity highlights that web components inadvertently built the perfect standard for annoying chat widgets and nothing else.
This conclusion, however, is not the end of the discussion. I plan to read Leah's perspective, but I want to first address the points raised by others. Ultimately, while I can acknowledge that there are ergonomic benefits to using web components in certain scenarios, the cost that it imposes everywhere is steep. It is important to recognize that although technology can enable poor patterns, it is challenging to support it when it rarely fits into the ideal scenario. At best, it represents nominal overhead.
The crux of the issue is that web components are compromised through and through. Although compromises are sometimes necessary, they are not something to be excited about, and some compromises are better than others. I was presented with the notion that in 10 years from now, it is possible that no one would be using Solid, yet a web component might still exist with the same interface as today. However, I countered that I would still choose to build with Solid because it represents the best choice for today. Even if I had to use an outdated version of Solid, it would still be superior to the web component version.
I hope that in 10 years, I will be using something better. I am increasingly weary of the argument that the things you're using today are going to die and that you need to adopt standards because they will endure. Thanks to these standards, an old Solid JS codebase will still work in 10 years. It may not be enjoyable to work with, and the documentation might be outdated, but the same can be said for web components. The reality is that I work in React codebases from eight-plus years ago, and while they are not perfect, they haven't degraded over time; rather, I have simply become accustomed to better tools.
The assertion that standards in the web are better than frameworks for longevity is rooted in the fact that standards do not improve. As Adam pointed out, I have 5-year-old web components that still work, and I also have 8-year-old React class components in production that still work. The difference lies in the fact that most React developers prefer not to work on old class components, whereas web components have not suffered the same fate because nobody ever wanted to use them.
The ongoing improvement in developer experience within React and other frameworks does not serve as a victory for web components. In fact, they are worse than React was 8 years ago, and they will likely be worse than using React today in another eight years. This argument is fundamentally flawed, and I am glad that Ryan has also called it out, as I have long disliked this line of reasoning.
In essence, there is nothing inherently wrong with web components, provided they remain true to their nature. The danger lies in the promise that they are something that they aren't, which distorts the surrounding ecosystem and poses risks to the entire web. This is a price that everyone has to pay.
To conclude, I encourage you to follow Ryan and check out his YouTube channel for more insights. Now, let's hear Leah's response. She asserts that web components are not framework components, and that’s perfectly acceptable. It is important to note that this post reflects my opinions, which do not necessarily represent the consensus of the entire web component community.
The blog post by Ryan Carneal titled "Web Components Are Not the Future" has recently sparked considerable controversy. Several other JavaScript framework authors have expressed their frustrations and disillusionment regarding web components. In response, some advocates of web components have written rebuttals, while others have sought to address the underlying issues for future improvement. I am eager to explore these frustrations further.
Web components face pushback not because they lack potential, but because they need a complete rethink to match the flexibility and capability of existing frameworks.
Existence warps everything around them, and that puts the whole web at risk. It's a price that everyone has to pay. Banger! Follow Ryan and check out his YouTube. Now, let's hear Leah's response: Web components are not framework components, and that's okay.
Disclaimer: This post expresses my opinions, which do not necessarily reflect the consensus of the whole web component community. A blog post by Ryan Carneal titled "Web components are not the future" has recently stirred a lot of controversy. A few other JS framework authors pitched in, expressing frustrations and disillusionment around web components. Some web component folks wrote rebuttals, while others repeatedly tried to get to the bottom of the issues so they could be addressed in the future.
I want to see the frustrations. It's probably the Vue thing I talked about earlier. If web components truly simplify frameworks while retaining the same level of features, I'd be the first one to rewrite Vue on top of it. I'm sure Ryan and Rich hold the same stance too. The conclusion is collectively: no, it's a tax and we should get over it.
Rich stated that the insinuation that there's some kind of vested interest in suppressing web components is both illogical and ironic, given the author's day job. It is really distasteful and totally misreads Ryan's argument. When everybody I've heard of says, "this sucks," and a bunch of people I've never seen before say, "wait, no, you're wrong," I trust the people I've heard of. I'm sorry, I just do. I know it's a bias, but all of the authors of all of the most popular tools on the web have made a pretty clear stance here.
Anyways, when you're on the receiving end of such an onslaught, the initial reaction is to feel threatened and become defensive. How these kinds of posts can often end up shaking things up and pushing a technology forward is noteworthy. In the end, I have some personal experience: after I published my 2020 post, "The failed promise of web components," which also made the rounds at the time, I was approached by a bunch of folks about teaming up to fix the issues that I described.
The results of these brainstorming sessions led to the formation of the Web Components Community Group (CG), which is for collaboration between people working on web component libraries, tools, documentation, and standards. This group was formed to try and make web components usable, and now, it has a life of its own. It has become a vibrant web component community that has helped move several specs of strategic importance forward.
As someone who deeply cares about web components, my initial response was also to push back. I was reminded of how many times I had seen this pattern before. It is common for new web platform features to face pushback and resistance. For many years, I saw that the example she gave on Twitter was that apparently people hated CSS for the first ten years and then came around to it. There were not established solutions that CSS was trying to poorly recreate; the established solution was tables, which were much less flexible and capable than CSS.
Web components are the less flexible and capable solution here. If the more flexible thing is already dominant, it will stay winning. That is what I didn't like about her argument: CSS didn't win because it was the standard or because it was pushed; it won because it was better. It was better because it was more flexible, and apparently, it wasn't originally; it was way more limited.
Nan, who is an absolute CSS and styling whiz, is the guy who made Styx, if you're not familiar, and is the only person to talk on Tailwind in a way that I can actually learn from. People hated how limited CSS was; they didn't hate the idea itself. When CSS became less limited, it became more popular. Web components are the limited option here, and the frameworks are the less limited option. There are deficient APIs which can be fixed by adding more stuff.
Also, a fair point: CSS needed more things to be better. Web components don't need more things; they need to be rethought. As Leah says here, we tend to compare new features and new platform stuff to the current userland practices, and their ergonomics often fare poorly at the start, especially when there's no immediately apparent 80/20 solution. Making things possible tends to precede making them easy.
That is a fair point. The first priority of the standards committees is to make things that can work at all and then make them easier and better. But once the standard is there, it's there, and it can't be undone. So, I think if you want to do that type of experimentation, frameworks are the right place, not the web platform. As she says here, web platform features operate under a whole different set of constraints.
Web standards are essential, but they need to evolve thoughtfully; rushing to standardize without addressing real user needs can lead to frustration and inefficiency.
Fair point: CSS needed more things to be better. However, components don't need more things; they need to be rethought. As Leah says here, we tend to compare new features and new platform stuff to the current userland practices, and their ergonomics often fare poorly at the start, especially when there's no immediately apparent 80/20 solution. Making things possible tends to proceed before making them easy. That is a fair point; the first priority of the standards committees is to make things that can work at all and then make them easier and better. But once the standard is there, it's there and it can't be undone.
So, I think if you want to do that type of experimentation, frameworks are the right place, not the web platform. As she says here, web platform features operate under a whole different set of requirements and constraints. They need to last decades, not just until a major release. They need to not only cater to the current version of the web platform but anticipate its future evolutions and be compatible with them. Additionally, they need backwards compatibility with the web as it was 20 years ago and must be compatible with a slew of accessibility and internationalization needs that the userland libraries often ignore at first.
That's not fair; userland libraries have not been ignoring these things for a while, and there's plenty of standards like canvas that are not particularly accessible. It's a good point from Nan here: the web component API breaks a whole bunch of expectations of how HTML and the DOM work. It's not a browser standard, and yes, it's weird. Canvases are breaking a lot of the same rules here. When we start on web GPU, it's really cool, but it's chaos.
That all said, most modern frameworks put a lot of work into things like accessibility. Just because tools 15 years ago didn't, doesn't mean that this is a fair statement. In fact, tools like React yell at you when you're not making things accessible; tools like Spelit do the same. I just don't agree with this point anymore.
The last point she has here, though, is that they're developed in a distributed way by people across many different organizations with different needs and priorities. So, they're designed by committee, which is not necessarily a good thing. Usually, the result is more robust, but it takes a lot longer. That's why I've often said that web standards are product work on hard mode. They include most components of regular product work, like collecting user needs, designing ergonomic solutions, balancing impact over effort, and leading without authority, but with the added constraints of a distributed, long-term, and compatibility-focused development process. This would make most PMs pull their hair out in frustration and run screaming.
I totally agree here: making web standards is hard as balls. I would argue this means you should be pickier about which things you bother going the web standard path with. I don't think web components were a thing worth standardizing until way more of this work was done, if at all. They have not played out in a way that I see them as beneficial.
Here's the CSS thing I mentioned before: I'm old enough to remember this pattern playing out with CSS itself. There was a huge pushback when it was introduced in the '90s; it was clunky for layouts and had terrible browser support. "Why fix something that wasn't broken?" folks cried. Embarrassingly, I was one of the last holdouts. I liked CSS for styling, but I was among the last to switch to floats for layouts; tables were just so much more ergonomic. The majority resistance lasted until the mid-2000s, where it went from "this will never work" to "clearly this was the solution all along" almost overnight. The rest, as they say, is history.
But the more I thought about it, the more I realized, as often happens in these kinds of heated debates, the truth lies somewhere in the middle. Having used both several frameworks and several web components, and having authored both web components and even one framework over the course of my PhD, I can say that both sides do have valid points. Frankly, framework authors were sold the idea that web components would be a compiled target for their frameworks, and they got today's web component APIs. I understand their frustration. Worse yet, if every time they tried to explain that this sucks as a compile target, they were told, "No, you just don't get it," or worse, that they should just work harder or that they're biased because they're framework authors, you'd feel gaslit too.
Yeah, damn right: web components are still far from being a good compile target for not all frameworks, for any framework not explicitly built around them. That's the one change I'd make here, but that's not a prerequisite for them being useful. Do I need to go back to the thing I just played from Nicole, where she said the real web isn't using browser standards; they're using frameworks that are built?
Web components promise flexibility, but the reality is a frustrating struggle between general and project-specific needs, leaving developers feeling lost in a sea of complexity.
The discussion around web components has been fraught with challenges, particularly regarding their role as a compiled target for various frameworks. Many developers have expressed their frustration with the current state of web component APIs. This frustration is compounded when they attempt to articulate their concerns, only to be met with dismissive responses suggesting that they simply "don't get it," or worse, that they should "just work harder." Such reactions can feel gaslighting, leading to a sense of disillusionment among those who are genuinely trying to engage with the technology.
Web components are still far from being a good compile target, especially for frameworks that are not explicitly built around them. However, this does not preclude them from being useful. As Nicole pointed out, the real web is not solely reliant on browser standards; rather, it utilizes frameworks that are built upon these standards. Consequently, anything in the browser that lacks value or compatibility with frameworks is often deemed a bad browser API. It is unfortunate that web components represent a last bastion of an outdated era, deeply entrenched in complexities that are difficult to resolve.
My hypothesis is that the primitive nature of elements means that higher-order web components, such as a card component that incorporates a button component, an avatar component, and others, do not compose well. However, it appears that with the use of slots, many of these issues can be addressed, and the composition becomes functional. Personally, I find the slot behavior less appealing. I prefer slots to function as properties of component props, similar to how they operate in React. In React, a slot is defined as a prop that can be placed anywhere, and there is also a built-in default slot through props.children. In contrast, web components require the use of slot="..."
to bind specific named items, which, while functional, lacks the pleasantness and control offered by React.
The landscape of components can be divided into two categories: project-specific components (like a user hover card or a survey question) and generic components (such as a tab group or a button group). However, the community often conflates these two categories, largely because frameworks do not differentiate between them. The term "component" has become a hammer used to address every nail. Conceptually, there are two core categories of components: generalizable elements that can be utilized similarly to native HTML elements across diverse projects, and reactive templating UI models that serve specific purposes within a project.
For instance, a rating widget might be unique enough to a project that it should not be considered generalizable. However, the line between what constitutes a generalizable component and what is project-specific is often blurred. At what point does a ratings widget transition from generic to project-specific? Similarly, a combo box may start as a generalizable element but become tailored to a specific implementation.
The second type of components proposed involves reactive templating UI models that are designed for specific projects and may not have utility outside their niche applications. For example, a font foundry might create a component to demo a font family, including child components to showcase different styles. The applicability of such a component outside its specific context would be quite limited.
This ambiguity is frustrating, as I do not want to constantly ponder whether a new component is generic enough to qualify as a web component or if it is too specific and should be categorized differently. This ongoing dilemma has prompted me to delve deeper into the perspectives shared by Rich and Evan, as they articulate that instead of simplifying their tasks, web components are complicating their work. This raises significant questions about the viability of web components as a foundational building block in modern application development.
Web components complicate development, creating a hidden tax that slows down frameworks and frustrates developers.
The discussion surrounding web components and their integration into existing frameworks highlights a significant challenge for developers. The component outside of the very niche font foundry use case would be very limited. Many developers feel that the line is blurry with so many of these technologies, and the relationship between the parts can be confusing. One developer expressed, “I don’t want to have to think about this whenever I’m making a new component. Is this generic enough that it can be a web component, or is it specific enough that I have to make it something else?” This ongoing struggle is frustrating, leading to a desire to explore the insights shared by Rich Ryan and Evan.
They articulate that instead of making their jobs easier, web components are making their jobs harder. The conversation revolves around using web components as a building block, similar to native elements. However, it seems that they are discussing using them as a compile target, which is not correct. The tax associated with this stems largely from the fact that frameworks need to be able to consume web components. This situation creates a steady source of nasty edge cases, causing framework code to be larger and slower.
As one developer noted, “Web components don’t follow the existing standards for the DOM; they behave differently from how the DOM behaves.” This discrepancy means that existing code in frameworks cannot simply work with web components. It has taken a long time for the React team to get web components to behave at all in React, and this is not due to a lack of effort; rather, it is because the integration is inherently problematic.
Interestingly, Matt pointed out that the criticisms of web components often reflect criticisms of HTML and the DOM, even though web components break our understanding of HTML and the DOM. Rich has a compelling response to this issue, stating, “I reject the premise that pushing the burden onto users is desirable.” He emphasizes that a tax has to be paid, and it is better for frameworks to shoulder that burden. Beyond the complexity that web components introduce, this directly affects users in subtle ways. For instance, if you want to clone some DOM to build a component, you can do so with fragment.cloneNode(true)
. However, this process becomes complicated if the DOM contains a custom element, as the clone won't be assigned to the correct class until it is appended to the document.
Furthermore, if properties are set in the meantime, it won't trigger accessors; instead, they will shadow the prop type, which is problematic. This creates a real head-scratcher of a bug. Developers often assume they can clone nodes to perform tasks, but this assumption fails when web components are involved. Fortunately, there are fixes available. It turns out that using document.importNode(fragment, true)
works correctly, but this is not information that one would casually learn while reading MDN. Instead, it is knowledge acquired through experience, often accompanied by “a side helping of battle scars.”
However, there is a catch: importNode
is roughly 30% slower than cloneNode in testing, which is unacceptable overhead, especially since most people are not using custom elements frequently. Consequently, developers opted to pay a different price; the compiler adds a flag to the generated code, indicating which method to use. This results in extra code and additional work, albeit a minuscule amount that would be unnecessary if developers didn’t have to navigate these complexities.
The bug tax, the solution tax, the implementation fix tax, and the documentation tax all contribute to the burden of working with web components. This includes adding regression tests, running those tests on every CI job, and shipping extra code. The cumulative effect of these taxes means that framework authors could ship sooner and produce leaner, more reliable code if it weren't for this poorly designed primitive with its myriad of edge cases.
One developer expressed their respect for Leah, stating, “You know how much I respect you; you know how much I love the way you’ve challenged me in the way I think.” However, they disagreed with the notion that the burden is acceptable because the value is not apparent. They remarked, “It’s always a tax having to change how your framework works because the browser added something new.” Reflecting on their experiences, they noted, “If I could build someone for the time I’ve spent working around web components in Spelt, I’d be a rich man.” The tax is real, and the cost is high. A great question posed by Ryan in the chat was, “Whose onus is it to show the value?” This remains an open question in the ongoing discussion about web components and their role in modern web development.
Building reliable code shouldn't feel like paying a tax for every new feature; it's time to rethink our approach to web components and frameworks.
In the discussion about more reliable code, there are concerns regarding the ill-designed primitive with its myriad of edge cases. I want to express my respect for you, Leah, and how much I appreciate the way you challenge my thinking. However, to you, it feels like a tax because you're not seeing the value in it. I do not like this reply; I liked the bits that I read here. It's always a tax having to change how your framework works because the browser added something new.
I recall a call from Rich earlier—if I could build someone for the time I've spent working around web components in Svelte, I'd be a rich man. The tax is real, and it's just one of those things where the cost is really high. If he saw the value in it, the tax of building around it would still be real. Great question from Ryan in the chat: whose onus is it to show the value? Apparently, it's ours, which sucks because I haven't seen it. Maybe it's Intercom's onus to show it.
Ryan, I hope you're enjoying your vacation and that you chose to be here voluntarily; you don't feel pressured to attend. Thank you for showing up! You missed the rant I went on about how okay I was with you not being here. I'm proud that your article is good enough to stand by itself; you can orchestrate an entire drama unintentionally without even being around for it, which is awesome. Your article is so good that the whole thing is just playing itself out now.
I want to give one more fun call-out here to Jenna, who I absolutely adore. She's one of the core contributors to Radic and arguably one of the people most responsible for its existence, so you can thank her for something as awesome as Shad Cen. Huge shout-out to Jenna, one of my favorite people in the space!
I feel this so badly: if Shadow DOM requires this many new specs to support stuff that Shadowless DOM can mostly already achieve, when do we acknowledge it was perhaps the wrong abstraction and try again? There’s so much fire in this conversation. Of course, back to the article, it's a spectrum—few things in life fit neatly into completely distinct categories. For example, an HTML demo component might be somewhat niche but would be useful across any site that wants to demo HTML snippets, like a web component library, a documentation site around web technologies, or a book teaching how to implement UI patterns, etc.
However, the fact that it's a spectrum does not mean the distinction does not exist. There are a lot of distinctions that exist that I don't think necessarily matter. For instance, the distinction between gray pants and blue pants is real, but they're both still pants, and at some point, you have to decide if it matters or not.
L components primarily benefit the use case of generalizing elements that extend HTML, which are still painful to use for reactive templating. Fundamentally, it's about the ratio of potential consumers to authors. The huge benefit of V components is interoperability: you write it once, it works forever, and you can use it with any framework or none at all.
Here's your tax: when you say that it works with every framework, it doesn't just magically work with every framework. Those frameworks have had to do crazy things to make it work. I would wager that the amount of effort that framework authors have put into making web components work within them is greater than the also admittedly insane amount of effort that was discussed earlier with the product work on the hard mode statement. Yes, making web components and the standard is an insane amount of work; I'm not going to pretend otherwise.
But you need to stop pretending that it hasn't been as much, if not more, work for the authors to do the same thing. What's annoying to me is that everyone had to work really hard for a standard that not very many people were actually asking for. So if you're going to claim that interoperability is the big win with web components, you all should be the ones contributing to Svelte, contributing to React, and contributing to these other things. It makes no sense to fragment efforts to re-implement things like tabs or rating widgets separately for each framework-specific silo; it is simply duplicated busy work.
It's funny because I argued against this before knowing this was the point that she was going to make. I said that a ratings widget is absolutely on the line where I want to do something different with it. This is why something like Shaden is beating out existing component libraries. With Shaden, you're cloning code into your codebase, so when it comes time to make it more custom, you own the code. With web components, you have to put in all this work to make it even work in your framework because of the assumption that you might never actually need to modify that component.
With Builder.io's crazy stuff that they're doing, you can take your React code and port it to every other framework.
The push for universal web components often leads to more complexity and duplication of effort, making it harder for developers to create and share truly reusable code.
For each framework-specific silo, it is simply duplicated busy work. It's funny because I argued against this before knowing this was the point that she was going to make. I said, "a ratings widget is absolutely on the line where I'm going to want to do something different with it." This is why something like Shaden is beating out stuff like component libraries that already exist. With Shaden, you're cloning code into your codebase, so when it comes time to make it more custom, you can. You own the code.
With web components, you have to put all this work into making it even work in your framework because of the assumption that you might never actually need to modify that component. With Builder.io's crazy stuff that they're doing to make it so you can take your React code and port it to every other framework, all of those efforts make the 50 lines of code for a ratings widget being sharable matter a hell of a lot less. It just feels like a weird thing to make the framework authors do this much work so a ratings widget could theoretically be shared across projects instead of it being part of the browser standards. I just don’t see it. The amount of work to port each of these things is low enough, especially now.
Fair point from N man: it's meant to be a common interface, even if it's flawed. The proponents of things like that at least exist. I can understand why people want a common interface, but if that common interface is bad enough that everyone is repeating their stuff and doing all this crazy work to make it work, at one point, the benefit isn't there. Thank you, Ryan. "It's mitosis," is the thing that Builder.io made to write your code once and have it work in every framework without web components.
As a personal anecdote, a few weeks ago, I found an amazing JSON viewer component, but I couldn't use it because I don't use React. I prefer Vue, and to this day, I've not found anything comparable for Vue or vanilla JS. This kind of fragmentation is sadly an everyday occurrence for most developers. Let me take a look at this. I'm assuming it's on GitHub because I would bet writing this in something like web components would be miserable. I bet this is a lot of code for this.
Look at all of the code for this. Has anybody made a web component this big that's open source and not absolutely miserable to work in? Once you get to this level of dynamic, it feels really hard to make that a web component. If anyone has an example of something this complex that's open source in a web component, I would genuinely like to read through it and look at the code. But it's hard for me to imagine. Model viewer from Google is the only example, and it's something Google made. It's still using packages and it's using Lit. It's still using a framework. You can't build something this large without a framework of some form. It's cool that it's a web component so it's reusable, but you still need a framework.
As for the JSON viewer thing, it is much harder to write things that complex with web components. Even if you do, you're going to need to pull in something like Lit. Lit had to be built to make web components usable. My counter here is that, on one hand, it does suck that this amazing JSON viewer can't be used in things that aren't React. I mean, you can mount a small React thing inside of a Vue or Svelte app, but it's just not fun. On the other hand, I don't think it's fair to push that developers like them have to learn this other new thing that is significantly more complex with all of these foot guns for the potential of people using it in these other things.
Especially if it means the interoperability of working inside of React, Vue, or Svelte is worse. If React is being used by 70% of their potential users, and writing in React makes it easier to bind, pass client, or children to do all these other things, it is really hard to justify rewriting that or writing something like it in web components instead. This is especially true if we get to the point where generating and rewriting this code for Vue or Svelte gets easier due to all the new tools and AI that are happening.
When it comes to project-specific components, the importance of interoperability decreases. You typically pick a framework and stick to it across your entire project. Reusing project-specific components across different projects is not a major need, so the value proposition of interoperability is smaller. Additionally, the ergonomics of consuming versus authoring web components are vastly different. Consuming web components is already pretty smooth; the APIs are largely there to demystify most of the magic of built-in elements and expose it to web components, with a few small gaps being actively plugged as we speak.
Web components have the potential to empower developers and designers alike, but until they become more accessible for everyone, their true impact will remain unrealized.
The discussion revolves around the evolving landscape of web components and their usability, particularly in the context of new tools and AI that are making code generation and rewriting easier. The importance of interoperability decreases when it comes to project-specific components. Typically, developers pick a framework and stick to it across their entire project, which means that reusing project-specific components across different projects is not a major need. Consequently, the value proposition of interoperability is smaller.
Additionally, the ergonomics of consuming versus authoring web components are vastly different. Consuming web components is already pretty smooth; the APIs are largely in place to demystify most of the magic of built-in elements and expose it to web components, with a few small gaps being actively addressed. However, there is a significant challenge when it comes to consuming these components in other frameworks. As Nicole established earlier, most websites are being built using various frameworks. While writing vanilla HTML and mounting a web component is straightforward, the ability to take a web component and mount it in a React app, passing properties and ensuring everything works properly, is still far from smooth sailing. Thus, it feels unfair to claim that consuming them is easy when the predominant way the web is built complicates this process.
Despite these challenges, even Leah agrees that authoring web components is miserable, especially without a library like Lit. The process of authoring web components remains painful and tedious, with many pitfalls for generalizable elements. This trade-off is considered acceptable since the potential consumers of these components are a much larger group than the authors. As an extreme example, nobody complains about the ergonomics of implementing native elements in browsers using C++ or Rust. However, when using components as a templating mechanism, authoring ergonomics are crucial since the overlap between consumers and authors is nearly 100%.
Leah conducted a Twitter poll to gauge the community's understanding of web components. The results indicated that over 80% of people who knowingly use web components are also web component authors. This statistic highlights a significant problem: web components are intended to empower users, not just to be consumed by expert web developers who can also write them. Until the number of authors decreases significantly, web components will not have reached their full potential. This realization is one of the reasons I joined the Web Awesome project, as I believe it is the right direction for web components. The goal is to encapsulate complexity into beautiful, generalizable, customizable elements that empower users by extending what HTML can do.
Web components can be utilized by developers to create gorgeous UIs, by designers to achieve more without needing to learn JavaScript, or even by hobbyists who struggle with both. Interestingly, Shad Cen shares a similar goal of creating reusable base pieces that are incredibly useful for web developers. For instance, there are custom form elements that simplify form handling, hover cards that display fancy information on hover, and more complex components like radio groups and select elements, which can be cumbersome to implement correctly.
There exists a spectrum of components, with one end representing basic HTML elements like <div>
and <button>
, and the other end representing the specific components I write for my codebase. My main concern with the article is that it describes these as two distinct categories, whereas they are merely two points on a spectrum. General components lean more towards the basic side, while reusable components built within my framework are closer to the project-specific end.
Customization is key; owning your components leads to better solutions than relying solely on web components.
In the discussion about web components, there exists a spectrum of elements ranging from those I have written in my codebase to base HTML elements. On one side of this spectrum, we find elements like div and button, while on the other side, we have the components that I create for my codebase, which I will refer to as components for clarity. My primary concern with the article in question is that it presents these as two distinct entities, whereas they are merely two points on a spectrum.
General components lean more towards the project-specific side, whereas reusable components built within my framework are situated closer to the base HTML elements. Within this spectrum, there are various stop points. For instance, web components are customizable to the extent they are exposed, but you cannot fundamentally alter their logic unless you fork them and make changes. Similarly, libraries like Material UI are quite close to base HTML elements.
As an ecosystem, we have learned that being too close to base HTML elements can be limiting, which is why we are shifting towards solutions like Shaden. Shaden operates similarly to Material UI, offering a collection of components that you can use, but importantly, it resides within your codebase, allowing for complete customization and ownership. The argument for web components suggests that ownership is unnecessary since they are extensions of HTML elements in the browser. However, as soon as a component becomes customizable, valuable, or complex, the need for customization arises.
Within this spectrum, web components occupy a niche that many developers do not frequently engage with. This trend is evident as we are increasingly moving away from libraries like Material UI in favor of Shaden. The industry is trending towards the right side of the spectrum. While web components advocate for better solutions on the left, it is unrealistic to expect developers who favor the right side to invest significant effort into improving something that has already been deemed less valuable.
With Shaden, as I have mentioned multiple times, you clone the code into your codebase, granting you full ownership and customizability. This approach provides the ergonomic benefits of reusable components without compromising ownership. However, it's worth noting that this solution is currently limited to React. While this may seem restrictive, if it were to support other frameworks, it would necessitate a different ownership model that might not work as effectively. For a React developer using Shaden, if they need to modify a web component and are unfamiliar with its complex syntax, the benefits of having it in their codebase would diminish.
Theoretically, one could add numerous attributes, properties, and flags to the components on the left side of the spectrum to avoid customization. However, eventually, the need for further customization or the realization that something is missing will arise, and owning the component resolves that issue. Notably, there are ongoing efforts to rewrite Shaden for other frameworks; for example, a project called Shaden Svelte is in progress, which aims to recreate all components for Svelte. This initiative underscores a consensus that Shaden represents the right solution. Solid also has a similar approach, with components that appear nearly identical.
Returning to Leah's article, framing the discussion as a dichotomy between frameworks and web components is misleading. Frameworks inherently utilize native HTML elements in their components, while web components enhance the capabilities of these native elements, facilitating the creation of project-specific components across various frameworks. As Rich pointed out, this assumes that framework authors have learned the nuances of web components and have developed solutions to address their deviations from native elements, which adds complexity to the discussion.
Moreover, while we may still require frameworks for non-trivial applications, web components simplify the development process. I would like to reiterate Nicole's earlier statement, which was supported by the Chrome team, indicating that all real teams and projects are currently utilizing frameworks. Therefore, it is essential to recognize the evolving landscape of web development and the role of both frameworks and web components within it.
Web components simplify the creation of project-specific elements, but complex applications will still benefit from frameworks. Let's embrace both instead of pitting them against each other.
Frameworks already use the native HTML elements in their components. Web components extend what native elements can do and thus make crafting project-specific components easier across all frameworks. As Rich established, this assumes the framework authors have learned all the ways that web components don't follow the rules of what native elements do and have built solutions to all of those. This makes this a much more painful paragraph to read, knowing that it is missing that core point.
Additionally, we may still need frameworks for non-trivial apps, but web components make their job easier. I would once again cite Nicole's statement earlier, where it has been established by the Chrome team that all real teams in projects are using frameworks now. I don't think we are the ones doing the pitting. I really haven't seen examples from people like Rich Harris or Ryan Carni, or any of these anti-web component advocates, saying, "Why would we do that? React components are better."
We have had a discussion about how hard it is to use web components and how it doesn't seem like they're solving a real problem, but that is different from saying React is good and web component is bad. I think I'm probably the closest thing to that, and my diagram I just drew is probably the closest thing we will get to the point where web components are more ergonomic to author. However, first, we need to get the low-level foundations right. At this point, the focus is still on making things possible rather than making them easy.
The last remaining piece of the puzzle includes things like reference targets for cross-root areas or element internals to allow custom elements to become popover targets or submit buttons. Wait, are you telling me that right now you can't have a web component button that is a submit button? Please tell me that's not true. Not true? Okay, just making sure. Thank you, chat, for clarifying.
Okay, Nan says he's unsure, which makes me much more skeptical now. You know what? Tiebreaker! I promise you guys I wouldn't make you look at web component syntax. I'm so sorry if this is confusing. That has attribute form form ID; get attribute form button Shadow root query selector button; set attribute form form ID. You see, to manually set the form ID and manually render the type submit on it.
So apparently, according to Deon, there has been pushback to allow for custom elements to be like form elements, specifically form-associated for that purpose. Let's ask Claud about it. I hope you guys can understand that, yes, I don't know all of the different things you can do in web components, but the whole point is that they're browser standard. Why are there 15 APIs for everything with them?
Here's the form-associated button code: form-associated is true; attach Shadow root; put the styles in button part equals button; slot slot button. Where is the submit bound, though? Is it not? Oh, it's a web component; it requires JS anyways, but you're not using type as submit anymore. Now you're using this internal form request submit. I can't take it in good faith; I'm sorry.
Do you know how I do this in React? Function demo form return form input type equals text form save. So it formats. Say I want a normal button for submit type equals submit. If I want that to be a custom component in React, I can create a custom button function.
Cut, paste, done. If I want this to be a custom button that isn't always type submit, I can do that too. Props type string. I could be more specific with the type if I wanted to. Type equals props type; type equals submit. I'll add that; that's going to be... say it has to be one of these. Cool, since this is TypeScript and TypeScript is smart.
Yoink! Well, let's do that. Now I can pass any of the button element types. Is that easy? There we go. Perhaps eventually, components will even become viable for reactive templating use cases like the open styleable Shadow Roots proposal, declarative elements, or DOM Parts. All these are some of the early beginnings of that direction in declarative Shadow DOM, paving the way for SSR among other things.
Then, and only then, they may make sense as a compile target for frameworks. But as Rich established, it's not just the compile target; it's interoperability inside of a framework. Components are not even the best reuse mechanism for every project-specific use case for list rendering components or overkill compared to something like v-for. By then, frameworks will be doing even more.
It is by definition that frameworks are always a step ahead of the web platform, not a failing of the web platform. As Cory said, frameworks are a testbed for new ideas that may or may not work out. They are also how the web is built. I feel like Leah has a fundamental disagreement with the research and effort that Nicole put in, which really hurts to know.
The bottom line is that web components reduce the number of use cases where we need to reach for a framework, but complex large applications will likely still benefit from one. So how about we conclude that frameworks are useful and web components are also useful? Let's stop fighting and go make awesome things using whatever tool we find most productive.
Once this article ends with, "We are sorry that this has made authoring frameworks much harder and that the interoperability story has felt more like gaslighting and a lie," then I would be much happier with this article. However, I feel like it fundamentally ignored the pain that these framework authors have gone through. It tried to acknowledge how they felt gaslit, but it missed almost everything else here, and that's sad. I can't talk about this stuff anymore. Peace, nerds.
Subscribe to my newsletter
Read articles from Igor Berlenko directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by