DEV Community

Cover image for Web Components did not fail!
Danny Engelman
Danny Engelman

Posted on

Web Components did not fail!

My comment to yesterdays Dev.to post: Web components failed. We can fix them became a full post:

Web Components Never Failed

Web Component history

The Web Component story didn't start with today's Custom Elements.

Almost 28 years ago, in 1998, Microsoft proposed HTML Components (HTC):

https://www.w3.org/TR/NOTE-HTMLComponents

Mozilla took its own stab at componentizing the Web with XBL, first developed for Mozilla and later proposed as a specification:

https://www-archive.mozilla.org/projects/xbl/

Different technologies, different APIs — but the same underlying desire:

Make pieces of the Web reusable, encapsulated, and programmable.


Browser vendors were already building Web Components

Browser vendors have been using Web Component machinery for many moons longer than we mortal developers have had today's standardized Web Components APIs.

To Us, Modern Web Components became broadly available roughly around:

Chrome 2016 · Safari 2017 · Firefox 2018 · Edge 2020

But browsers themselves have always had that same problem to solve:

  • The WHATWG specifies what an HTML element should do.

  • Browser vendors still have to decide how to build it.

Take a complex native element such as:

<input>
<textarea>
<video>
Enter fullscreen mode Exit fullscreen mode

From the developer's perspective, that's one element.

Underneath, there may be an entire internal UI: buttons, sliders, labels, tracks, controls and state.

That should sound familiar.

It is the same shadowDOM architecture us mortal developers can now use!

<video> with sahdowDOM in Chromium

Chromium video Shadow DOM

<video> with shadowDOM in Firefox

Firefox video Shadow DOM

With the appropriate DevTools settings, browsers can expose these internal trees for inspection.

They're not your DOM to manipulate.

They're implementation details.

And that's precisely the point.


Web Components did NOT fail

So saying:

"Web Components failed."

has always sounded a little strange to me.

We interact with componentized browser <input> UI every single day.

The browser platform itself demonstrates why encapsulated components are useful.

The question isn't whether components work.

The interesting question is:

Why don't we build more of our own software that way?



Mortal developers and Web Components

I think part of the problem is that we keep thinking in Apps.

Frameworks encourage that.

They scaffold applications.

They give us routing, state management, rendering systems, build pipelines, dependency graphs and application architecture.

And that's perfectly fine when you're building an application.

But:

Frameworks scaffold Apps.
Components are components.

A component doesn't necessarily need to know anything about your application.

A <date-picker> doesn't care whether the surrounding application uses React, Vue, PHP, Django or plain HTML. Or the car is painted red.

A <relative-time> shouldn't need to know either.

Neither should:

<car-tire>
<steering-wheel>
<playing-card rank="Queen" suit="Hearts"></playing-card>
<mark-down src="playing-card-component-usage.md"></mark-down>
Enter fullscreen mode Exit fullscreen mode

They should just work.



We're still building like it's 1899

There's another problem.

Many developers learned one particular way of building software and then taught those patterns — directly or indirectly — to AI.

So AI happily reproduces them — and teaches the next generation that this is simply how software is built.

Ask AI to build something and you'll often get an entire application architecture when what you actually needed was:

<something-useful>
Enter fullscreen mode Exit fullscreen mode

The tool isn't necessarily wrong.

We're asking it to build the wrong thing.

That's a mindset change.

Change your perspective from:

Everything is an App

to:

Apps with frameworks. Components with Web Components.

There are Henry Fords out there already working differently.

And I suspect some of them aren't shouting about it.

Why would they?

Once you've trained your tools — and your AI — to produce small, independent components instead of miniature applications, it can become a competitive advantage.


"I can do Web Components better!"

In 2022 there were already around 60 Frameworks, Libraries and BaseClasses listed in:

I-can-do-Web-Components-better (aka All the ways to make a Web Component)

Sixty!

And here's where I think we repeatedly take the wrong turn.

You discover Web Components.

You develop a few helper functions.

Then:

Oh, it needs this feature...

Then another feature.

And another.

Soon you've created conventions.

Then abstractions.

Then dependencies.

Then documentation.

Congratulations!

You're building a framework
And your ego just publsihed it to NPM

Instead, write the abstractions you need for your components.

They don't have to become somebody else's architecture.

They don't even have to be shared abstractions in your "Design System" components!
A well trained AI is great at managing those.


What about (Google) Lit?

Yes, I consider Lit a framework.

It provides its own abstractions for rendering, reactivity and component state.

That's useful if that's how you want to work.

But it's not the only way to build Web Components.

You don't have to write Lit's HTML template blobs.

The DOM already has an API.

document.createElement("button")
Enter fullscreen mode Exit fullscreen mode

isn't primitive.

It's powerful.

You have the entire browser platform underneath you.

Use it.

Write a one line helper function (tell your PM its a mini-Framework)

const createElement = (tag,props={}) => 
                       Object.assign(document.createElement(tag),props);
Enter fullscreen mode Exit fullscreen mode

And you are really using the platform!

customElements.define("the-obligatory-counter", class extends HTMLElement {
    constructor() {
        super() // sets and returns this scope
            .attachShadow({ mode: "open" }) // sets and returns this.shadowRoot
            .append(
                createElement("button", {
                    part: "plus button",
                    textContent: "-",
                    onclick: evt => this.count--
                }),
                this._count = createElement("count-value", {
                    part: "count value",
                    textContent: 0
                }),
                createElement("button", {
                    part: "min button",
                    textContent: "+",
                    onclick: evt => this.count++
                })
            )
    }
    set count(val) {
        this._count.textContent = val;
    }
    get count() {
        return ~~this._count.textContent;
    }
})
Enter fullscreen mode Exit fullscreen mode

Developing Web Components

Develop Web Components like you use .reduce():

No developer ever told you that you must use it exactly like they do.

That's the freedom Web Components give us.

There doesn't have to be one architecture.

There doesn't have to be one framework.

There doesn't have to be one correct abstraction.

Build the component.

Give it a useful API.

Let the browser do the rest.


So:

Web Components never failed.

Maybe we just haven't learned how to use them yet.

Browser vendors already showed us how.

Every <input>, <video> and <textarea> is proof that complex functionality can live behind one simple HTML element.

If Browser vendors can do it. Why can't you?



Top comments (1)

Collapse
 
pengeszikra profile image
Peter Vivo •

I’m also interested in web components, so I set out to demonstrate their usefulness.
There is a Markdown editor web component somewhere in my program, too—I think it’s worth checking out.