loading...
Ionic

Why We Use Web Components

maxlynch profile image Max Lynch Updated on ・11 min read

Web Components are all over Twitter (again), thanks to a great post by Rich Harris about Why [he] Doesn’t Use Web Components.

Rich details a number of technical (and non-technical) issues with the raw Web Components standard, specifically the Custom Elements and Shadow DOM APIs. Rich nails the technical details about Web Components on their own, but comes to a conclusion that we fundamentally disagree with if you just change slightly how you look at what Web Components are and how they should be used.

Note: this isn’t meant to be an attack on Rich. We are huge fans of his work, and Rollup in particular powers a huge chunk of our open source projects, including Stencil which we will talk more about here. That being said, we are major users of Web Components and feel the need to share our perspective!

The reality is, if you add a tool or library on top of Web Components, like Stencil, suddenly almost all of those issues go away and the power of Web Components really shine through. Unfortunately, the debate around Web Components vs a third party component system like React or Angular or Svelte seems to always compare the third party system with the raw APIs sans tooling, and arguments that involve adding tooling to get the same result are often not allowed in this debate.

This is unfortunate, because it keeps the focus on what the raw Web Component APIs can’t do on their own, instead of treating these APIs as low-level utilities that can be transformed into a really powerful tool if you’re willing to add some helpers on top. It’s also a bit of an unfair bar, since React, Angular, Vue, Ember, etc. have the benefit of tooling and helper libraries to add powerful functionality on top of the DOM which is why we use them in the first place. Without allowing tooling into the Web Component debate, we're effectively stuck comparing document.createElement to a higher level component system, which isn't productive.

With that in mind, I wanted to put some thoughts together on how smart tooling can help you solve the problems listed in that post, without really any of the downsides Rich details, and then talk about the actual problems that Web Components solve that aren’t solved by third party tools or frameworks today, why they are relevant and important, and why many developers are strongly embracing them today.

Addressing the issues

Let’s talk through some of the issues Rich outlines and how you can resolve them through tooling or helper libraries on top.

Server side rendering and progressive enhancement. On their own, Web Components don’t support server-side rendering and thus don’t work without JS on the client, among other related issues. However, SSR of Web Components can actually be accomplished by pre-rendering Web Components and re-hydrating on the client, and this can even work across shadow roots! Stencil has this feature available, and a similar technique as we understand it is being used by the Salesforce team for their Lightning Web Components. This enables clients that don’t have JS enabled and search engines to access a fully rendered version of each component instead of just the tag, thus avoiding this problem. Here’s one example of this in action and another example.

Flash of unstyled content and CSS in JS. To avoid a flash of unstyled content (FOUC), we can do a few things. One way is to only set components to visible once they are hydrated and styled. For example, Stencil tracks whether a component has hydrated, and only shows those components once their parent has loaded. This means when a component draws it is already fully styled, so no flash. Another technique is to use the Constructable Stylesheets API, which Stencil uses if available. Finally, we can share stylesheet information across components. That means multiple instances of the same component won’t have duplicate style data in each. With these techniques FOUC is a thing of the past.

Older clients need polyfills. Stencil automatically and dynamically figures out which clients need polyfills and only loads them if the client needs them. Turns out that number is actually really low, as most modern browsers (and mobile ones!) fully support the APIs used by Web Component authors. This fixes problem #4 in his post.

Controlling whether slotted content is rendered. In the DOM, elements load eagerly, which can make it tricky to build certain types of UI systems where content needs to load lazily (such as a router). The way to control whether an element is loaded is to not put it in the DOM in the first place, or to manage how you render slotted content in a specific component. Having a rendering helper on top such as Stencil or LitElement can help here. In practice we don’t find this to be much of an issue and have built a React Router inspired router using Stencil-built Web Components that we use across many of our Stencil web properties.

Confusion between Props and Attributes. Props and attributes have a bit of a tumultuous history in the DOM, and Web Components can make handling both more complex. However, a Web Component tool like Stencil or a library like LitElement makes it easy to build components that properly handle component props and changes to attributes without tons of boilerplate. Adding a type system like TypeScript on top can make it easy to handle typed props, and using web components inside of other web components (or through JS) makes the problem of passing non-string data to props trivial.

Rich’s code examples for prop/attribute management and custom element boilerplate rightly look terrible and no developer would ever want to write component code like that. Thankfully, if you look at the Web Component APIs as low level primitives, you don’t have to. Just use Stencil or LitElement or something similar and you’ll be able to write code that looks like your framework’s:

import { Component, Prop, h } from '@stencil/core';

@Component({
  tag: 'my-component'
})
export class MyComponent {
  @Prop() age: number = 0;

  render() {
    return (
      <div>I am {this.age} years old</div>
    );
  } 
}

Rich then finishes with a conclusion that these are all solved problems and it seems Web Components are just now getting to parity with third party component models. On one hand we agree, on the other we think Web Components actually do offer some meaningful improvements on existing frameworks.

For example, Stencil has proven using Web Components with smart tooling on top can help you get you some of the smallest, fastest apps around. Pushing more work to the browser has some benefits!

Stencil One bundle size

With all this said, we actually think the technical discussion around Web Components is less interesting than the non-technical side, and believe that by better understanding the non-technical side, we can start to see why Web Components are interesting at all and why their adoption has been growing steadily.

Hopefully we'll also show how Rich's conclusion that developers have been largely indifferent to the Web Component standard is really not true at all!

Solving Component Distribution And Integration

If Web Components were merely a poor replacement for today’s third party component models, none of us would be here arguing for them. Yet, here we are, so let’s talk a little bit about the problems that Web Components actually solve and the ones they don’t solve.

Sure, Web Components provide a native web component model, but component models are plentiful in frontend web development. Every developer using a popular frontend framework is well versed in creating components in their framework of choice. Clearly, just providing a native web component model isn’t solving a universal problem and this is a big chunk of the arguments against Web Components. The argument that usually follows is that third party frameworks can innovate on a component model quickly, while a standardized one like Web Components will always “be behind” and risk solidifying outdated approaches.

What problem does providing a native web component model actually solve then? Well, the biggest one it solves is being able to share and consume developer-created components directly in the browser regardless of application technology, and in a highly efficient way.

This is actually a real problem that teams have, but it’s a problem your team might not have! Are you building and consuming components across teams with a wide variety of present and future frontend technology choices? Does your company use React but just acquired a company that uses Angular? Do you need to integrate a Design System into a traditionally server rendered system like JSP/ASP.NET/PHP/etc.? Do you need to add modern JavaScript-powered components to legacy web apps or CMS’s that don’t have a traditional “framework” they run on? Are you building a UI framework like Ionic Framework that needs to work in any frontend technology?

These are the problems that Web Components uniquely solve, and for teams with these problems nothing else comes close to solving them. In fact, if you’re building a reusable UI library and not using Web Components, you’re in for a world of hurt and significantly limited addressable market over the long term, take it from us!

Who’s using Web Components today?

One of the things that always comes up in the Web Component debate is the lack of production examples of Web Component usage.

We have a few that we think demonstrate the problem that Web Components uniquely solve.

Let’s start with Ionic Framework. Started as a mobile UI library for AngularJS and then Angular, Ionic Framework went through a complete rewrite two years ago to move to a component model that would work in any web-based frontend environment, and we called this Ionic 4. We were motivated by business metrics like growing our community and addressable market, along with technical motivations like never having to rewrite Ionic again for tomorrow’s frameworks and dramatically improving load and rendering performance. I feel confident saying that Ionic Framework 4 is the most successful Web Component-based Design System/UI framework and with that, Web Components are now in thousands of app store apps, and nearly 4M new Ionic Framework projects are being created every year. That’s some serious Web Component usage! Best of all, Ionic Framework 4 developers probably don’t even know they are using Web Components since they integrate seamlessly in Angular as well as our upcoming React and Vue support.

Beyond Ionic, we have a mix of startups and large enterprises building with Web Components today. On the startup side, popular workout app Sworkit recently rolled out their new PWA and Native app using Ionic Framework 4, using Web Components both on the web and in the app stores.

You'd be hard pressed to find a bigger example than Salesforce which recently moved their Lightning components to Web Components and has been a pioneer in Web Component-based Design Systems.

Another example is the public company Upwork that recently shipped Web Components built with Stencil on their homepage.

And governments are getting on board, too! The State of Michigan recently rolled out a Design System based on Web Components and Stencil.

Finally, Stencil is increasingly driving a big portion of our business at Ionic. We recently signed on several name-brand enterprise customers, and the major theme across all of them is that Stencil and Web Components help solve major component distribution and creation problems they have across their many properties and teams which often don’t have a prescribed set of frontend technologies in use. We hope to be able to talk about more of these examples in the future.

Competing Visions

The Web Component ecosystem has a diverse set of players with different long term visions for what Web Components can and should do.

Some of these folks think Web Components should replace third party app frameworks. Others think that Web Components are really more suited for leaf/style/design nodes and shouldn’t get in the business of your app’s component system. And then there are hordes of app framework developers that don’t see the point at all or consider Web Components an affront to frontend innovation.

We’re somewhere in the middle, and don’t claim to speak for everyone in this space. Our long term vision is that app development teams continue to use their framework of choice, which we hope continues to get better and smaller and more efficient, with increasingly good support for targeting and consuming web components (of which big teams will be consuming an increasing amount of as companies continue to embrace Web Components for shared design systems).

At the same time, we believe the killer app for Web Components is solving those component distribution and Design System problems. We also believe that 90% of the market doesn’t have those problems, and find the current debate about the merits of Web Components a bit unproductive.

Oddly enough, from a business standpoint, the shape of this market is really appealing. Design Systems at Scale is a problem unique to larger teams and companies, which means there’s a natural strong enterprise business here!

Conclusion

Web Components are a controversial technology, with plenty of supporters and detractors. We agree there is room for improvement across the standard, and hope that Rich’s article, and others, can help browser vendors improve the standard moving forward.

I also understand that many of our counter-arguments won't be satisfying to developers that are adamant that Web Components will only be ready when they support framework features out of the box without any additional tooling.

With that said, we’ve always considered Web Components to be a low-level technology, and have been amazed at the power they have when paired with proper tooling and libraries like Stencil or LitElement. For teams that need it all, we really think Stencil is the best solution out there and will give you everything you want from a framework combined with some really powerful features not likely found in your framework of choice today, including the smallest code bundles, SSR/Pre-rendering, best PWA performance, and advanced lazy loading. And for teams Stencil can generate documentation automatically from your components, run visual UI regression tests, and generate native wrappers for Angular, React, and Vue. You can learn more about all of this on our 1.0 announcement post.

Web Components solve a very particular set of problems, of which many teams (especially smaller ones) don’t have. For those teams, creating Web Components will only bring marginal value over their app framework’s component model. However, we expect those teams will increasingly consume Web Components as UI library and Design System authors embrace the standard and its ability to solve that specific problem better than any other frontend technology.

For teams that do have these problems, no other technology adequately solves them, because no other technology is natively supported directly in the browser. Today, these problems are largely in bigger companies with less strict rules about usage of specific frontend technologies, or teams targeting the broader web development ecosystem where no single frontend technology has truly taken over (no, not even React).

If you're one of those teams, we hope you'll take a hard look at what Web Components can do if you just give them a little help. We’re confident in saying that Web Components are the best thing that ever happened to Ionic as a company and creator of an open source UI Design System, and we hope you’ll check them out if you have any of the problems talked about here!

Posted on by:

maxlynch profile

Max Lynch

@maxlynch

Co-creator of Ionic Framework. Creator of Capacitor. Programmer turned startup CEO

Ionic

The open source UI toolkit for developing high-quality cross-platform apps for native iOS, Android, and the web — all from a single codebase.

Discussion

pic
Editor guide
 

I work as a consultant for one of the big market research company, and over the past 2 years we have built a library of web components which is now being used across various projects in the company, and any new project that's getting started is using this library to bootstrap the application, and the library has few web components which have business logic tightly integrated into them.

The business is seeing the benefits of using web components, as teams are free to choose the framework they want to work on while still being able to use the web components.

 

We went on the way of writing our new UI kit in WebComponents using Stencil. We were suffering performance problems (using ~200) components on a single page, but it was reasonable. That was in Chrome but we checked Edge then. It took the site 20+ seconds to load! Upgrading to Stencil One then made it even worse. Seems like using slots is just not a thing using polyfills, it causes re-layout every time it moves an element in the DOM. After struggling for a month with it, we decided to port the kit to React components. Even solved every Chrome issues we had regarding performance. TLDR; WebComponents are fun, but if you need performance and your app has higher magnitude of complexity, native DOM ftw.

 

Hmm, something seems up. Did you ever file an issue? Can dig into it on our end. We have a number of apps with many more components than that without those perf issues.

As for edge, unfortunately due to the lack of native WC support the slot polyfill is used which can impact performance. We see this as a short term problem though it may impact certain users more than others depending on how many Edge users you target. Edge is really the last thorn in the side of WCs.

 

Funny ... Edge was supposed to be a complete rewrite that was going to solve all the issues with IE once and for all, right? Guess we were naive to believe it. They should have just used Webkit, less headaches for them and for the rest of the world. Microsoft under Nadella changed a lot, but old habits die slowly.

By the way, fantastic post, Max! Really impressive work with Stencil, and the case for Web Components (e.g. in a larger heterogeneous corporate setting etc) is articulated well.

 

Well, the most important Edge user for us is the company owner :D Don't tell me... :)

Hey do you have a demo of old version of the component system somewhere to look at? Granted we do not use Stencil in our systems but we had pages with hundreds of components and never faced issues like this even in IE.

Unfortunately not. It's not public. What I can tell is that we were deeply relying on slots with multiple levels of nested components supporting multiple slots also.

 

Great post! I think the only thing I am not sold on with regards to web components is the concept of hydration. It seems to me that the correct solution should not be to mimic render the component on the server and then replace the light dom with shadow dom after the page comes on line.

I would almost rather see some standardization around web components using the light dom for stuff that should be SSR, and the shadow dom for stuff that is "internal". I don't know exactly what the best approach would be, but I would like to see some exploration around alternatives to hydration.

Although I think the "right solution" will be the one that major web component based libraries and frameworks can agree on over the next five years. If everyone seems to come to an agreement on it I would go for it, but before the community comes to a decisive opinion I would like to see some other options explored.

 

"The reality is, if you add a tool or library on top of Web Components, like Stencil, suddenly almost all of those issues go away and the power of Web Components really shine through."

And there you go. If you have to have a framework to solve the problem, then you haven't really solved the problem. WebComponents do solve a problem, a problem nearly no team has. They are okay for low-level parts, but the API is clunky and dated. The web developer community has moved on from when the WebComponents spec was created, but the spec spent years in "development hell" waiting for all the browsers to implement it (and still some areas are not covered) and the polyfills required crippled some browsers. At this stage, the browser vendors should be shipping web components to spec out newer ideas. Not expect the dev community to take a step backward or embrace frameworks that have only a fraction of mindshare as the other web frameworks.

 

Hey Kevin, I already addressed several of your points in the post.

And no, it’s not the same as a framework because the output is portable, and that’s a huge difference. Whether you use Stencil or something else the components can work together without you having to use that framework, which is a huge difference.

As noted in the post if you’re not satisfied with tooling then you won’t be satisfied with my argument and that’s okay.

 

I recently gave a talk on web components, and I have wanted to like them for years. But the compromises they had to come to (like only supporting the class syntax) have hurt more than helped.

WebComponents have a place, and your case is a prime of example of that. But I would hate to tell someone just learning web development to learn and build something with them. Or that they would have to use another framework that pushes them even farther from javascript/html/css.

As primitives, yeah maybe. For application dev? I'd have to take a hard pass.

 

Nicely done. Love seeing posts correcting the record on the current state of web components.

 

Great and nuanced post, glad to see the discourse steer this way :)

 

Thank you, Max. I greatly appreciate you taking the time to write this.

 

Love this post! It’s so well written and to the point. Thank you!

 

love the post - read rich's first so this set me back on track. btw server side rendering and progressive enhancement - how can this be accomplished in stencil? can u refer doc or guide please?