Why We Use Web Components

Max Lynch - Jul 8 '19 - - Dev Community

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>
    );
  } 
}
Enter fullscreen mode Exit fullscreen mode

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!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .