I wish we never explained web components by "well, it's actually four different things, but I won't tell you which one you care about."

Spoiler: It's custom elements. It's always been custom elements.

Since forever, library authors have felt the pain of needing to match JavaScript with DOM elements. For instance, if you're writing a date picker, someone needs to call YourDatePicker.init(element) for every <input class="date-picker"> that gets attached to the DOM.

There is no built-in way or even standard way to do this. Every library shipped their own solution to this, using a jQuery plugin, global activation function, magic onload handlers or a framework-specific base class.

Custom elements make all of that go away. Just use in your HTML, or create it using the framework of your choice and it will Just Work ™. No JavaScript ceremony required to make a DOM element come alive. It's a giant step forward for how we bootstrap web apps, or how we share code between apps.

I think that leap is the reason we're seeing an increasing number of JavaScript libs switching to custom elements for script/element matching, although browser support is an unholy mess. Microsoft is dragging their feet with Edge and of course pretends IE11 doesn't exist anymore, while at the same time blocking upgrades from IE11 to Edge on Windows 7. Firefox hides it behind a feature flag. Safari mostly supports it with some caveats.

The polyfill from hell

"But we can polyfill it". Except you can't easily because it breaks assumptions of your build pipeline in interesting ways. You see, Chrome's native support for Custom Elements v1 requires native (not transpiled) ES6 classes because politics. And your app probably ships ES5 prototype spaghetti in production. So the Babel or TypeScript presets you use to support IE11 will break custom elements in Chrome.

Now you need TWO builds of every JavaScript file: One with native ES6 classes for Chrome and another with dumbed-down ES5 constructors for IE11. (hat tip to Lucas Dohmen)

Understanding and maintaining two build pipelines is totally doable for an experienced development team, but will probably keep custom elements out of the mainstream for now. An interesting date to note here is Jan 14th 2020, when Microsoft kills Windows 7 / IE11 and we might finally be able to ship ES6 code without transpilation.