DEV Community

Preet Shihn
Preet Shihn

Posted on

Why I use Web Components - My use cases

First of all, I am not a blogger or advocate of any technology, or speak at events/conferences. So mind my first attempt at writing. I hope I am clear in expressing myself.

I want to talk about some practical use cases and scenarios where I have found Web Components to be the best solution available.

Whenever I have seen discourse on Web Components, it usually devolves to API design and comparison to frameworks. I will not defend the API as I did not write it. I will not criticize it, others have done a better job at it.

Solved Problem?

It is often stated the components are a solved problem - look at all these frameworks with religious following!

Now, if you're developing an app, say a book recommendation app - you should write this in any framework you are comfortable with. Or write in only web components or write in HTML + Javascript circa 2000. All good. You should use whatever component system you want to, as long as it meets your goals.

But, if you want to write a rich component that is truly shareable, there is no other model available. You cannot use React components in Svelte or Svelte modules in React or in Vue or in Nimbus3000.

My Use Cases

I'm going to talk about real scenarios where I think using WebComponents seems like the right choice. The central theme here is shareable and cross-framework.

1. Embeddable Frontends (MicroFrontends?)

I help lots of websites add engagement and all sorts of bells and whistles to their sites. These sites are not maintained by fancy developers - think bloggers, artists, content creators, small businesses. Some of them get huge amounts of traffic (100M pages per month). We have a data engine that scans and monitors data on their sites and feeds them to embeddable frontends that add engagement to sites. Some examples:

  • Real time search that is customized to the user
  • Launch a dynamic game related to the content the user is interested in
  • Infinite list of related content

Embeddable Frontend Example

Most of these sites are on WordPress, Squarespace, Framework rendered using React, Vue. Our frontends get injected as WebComponents.
These publishers add the component wherever they want. No npm or fancy build process here.

Being in a web component shields the content from whichever theme they are using or whichever other frameworks that are running on the system. Some of these components interact with other content on the host page. They have to be highly performant and small in size.

These publishers usually have basic HTML knowledge and they add them to their content just like they would be adding images or videos.

2. Complex Widgets

The above example was a very customized solution, but then there are developers who create general widgets.

<model-viewer> is a perfect example of this one. It's been used all over the place like in NASA, and Shopify. I have no clue what framework Shopify uses (and it's probably not the same as NASA), but with the model-viewer available as a Web Component, they had a solution.

Same applies to so called 'design systems'. Ionic's components for example, developed as Web Components and then also wrapped for different frameworks like React, Vue.

3. Evolving HTML

HTML5 added all sorts of new tags to the spec like <video>. Will it never add any new tags? One argument is that DOM sucks and all new elements should be defined a completely new component format. Or more realistically, it will probably add more tags - people know how to use tags already.

One of the new tags being considered is a switch. To test out possible implementations, Chrome is shipping it as web component <std-switch>, because it essentially extends the built in elements. When not on Chrome, the web component could be loaded as a fallback module. Extending existing underlying element model has its values.

Personal story in this category: A friend of mine in grad school was trying to use MathML on some web page. (They are NOT a developer.) Chrome does not support MathML at the moment. They could have used some sort of library to render it. I implemented MathML as web components as a fun project, and they could use it in chrome with minimal changes.

MathML example

Styling

In some ways there is no such thing as Web Components in the platform. There are a few separate specs, like Custom Elements, and ShadowDom, being the main ones. More under development for importing CSS, HTML, JSON.

All of these individual spec have merit on their own, and their own design flaws, in the eyes of the developer. These can be used individually without being all web componenty.

Parts of the component that are not inside a ShadowDOM can be styled using your global stylesheet, where parts inside the ShadowDOM are isolated. This is particularly useful in the shareable component case which I focus on.

Shadow DOM

Developer Experience

A common complaint people have with WCs is that they are too verbose to code. It doesn't have bindings, or whatever. Like I said earlier, I'm not going to debate the merits and faults of the existing API and DX.

I do think that it is fair to use frameworks and libraries if you want to. I mean, you already do and you even compile at times. Some believe they should use no external libs at all, and that is a fine goal to strive for. But the reality is that it is much easier for most devs to use libs. So stop comparing DOM api to a framework API which could be compiled to DOM api. I think helper libraries are excellent. We already use it for so many other web tech like Web RTC, Workers, etc.

There are some great helper libs that will help you with WCs should you wish to. A few: Lit Element, Stencil, Haunted if you like hooks.

Example using LitElement:

@customElement('my-counter')
class Counter extends LitElement {
  @property({ type: Number }) count = 0;

  render() {
    return html`
      <div>${this.count}</div>
      <button @click="${() => this.count++}">Increment</button>
    `;
  }
}

Example using Haunted:

function Counter() {
  const [count, setCount] = useState(0);
  return html`
      <div id="count">${count}</div>
      <button type="button" @click=${() => setCount(count + 1)}>Increment</button>
  `;
}
customElements.define('my-counter', component(Counter));

Not your use case

My use case is not your use case. This may all mean nothing to you, but I thought you may be interested in hearing about a point of view from a different plane.

Top comments (9)

Collapse
 
bennypowers profile image
Benny Powers 🇮🇱🇨🇦 • Edited

Great write-up. Here's an example of your counter component written using hybrids. Devs might choose hybrids if they are looking to factor an app with a (mostly-)functional, highly composable component model.

import { define, html } from 'hybrids';

const inc = host => host.count += 1;

const MyCounter = {
  count: 0,
  render: ({count}) => html`
     <label for="button">${count}</label>
     <button id="button" onclick="${inc}">Increment</button>
  `
};

define('my-counter', MyCounter);
Collapse
 
smalluban profile image
Dominik Lubański

I didn't know that I have an ambassador of the project :) It so cool to see that other people uses your work.

Collapse
 
westbrook profile image
Westbrook Johnson

Great first foray into the written tech word! Love you work in the abstract; wiredjs.com/, brickception.xyz/, etc. It's really useful to hear a little more practically how you come to those ideas being useful in your everyday work.

Thanks so much for sharing!

Collapse
 
shihn profile image
Preet Shihn

Thanks. I'm always jealous of people who are excellent communicators, especially when writing. Never delved into it. Practice is the key I suppose.

Collapse
 
paulmaly profile image
PaulMaly

Actually, Svelte components are just stand-alone JS classes. So, you can use them in React/Vue/Angular/Whatever apps.

Collapse
 
shihn profile image
Preet Shihn • Edited

Theoretically sure. Not in the same way really. One of these works.

<ReactComponent>
  <SevleteComponent></SevleteComponent>
</ReactComponent>
<ReactComponent>
  <web-component></web-component>
</ReactComponent>

Also, WCs you can use is raw HTML as well or anywhere that takes html. So people who are not JS devs can use them easily (Not saying that WCs work without JS)

<body>
  <p>
    <my-fancy-image>
   </p>
</body>
Collapse
 
ackvf profile image
Vítězslav Ackermann Ferko

link please

Collapse
 
eligoh profile image
Elijah Goh

There's just so many library to choose from, anyone has a preferred web component builder lib and why?

Collapse
 
westbrook profile image
Westbrook Johnson

I like to work with LitElement as it’s super slim on file size and the lit-html renderer that powers it is both fast and highly flexible. As for building, it plays fairly well with whatever tooling you’d prefer to use. However, the team at open-wc.org/ has some great suggestions of using it in concert with their suggested bundler Rollup, as well as some additional documentation of working with Webpack.