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
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.
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.
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)
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.
I didn't know that I have an ambassador of the project :) It so cool to see that other people uses your work.
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!
Thanks. I'm always jealous of people who are excellent communicators, especially when writing. Never delved into it. Practice is the key I suppose.
Actually, Svelte components are just stand-alone JS classes. So, you can use them in React/Vue/Angular/Whatever apps.
Theoretically sure. Not in the same way really. One of these works.
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)
link please
There's just so many library to choose from, anyone has a preferred web component builder lib and why?
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.