I bring you another possibility, but it is not a framework but rather a set of native APIs.
No, it's not the holy grail of front-end development, but it's a promising alternative that, throughout this series of articles, we'll be uncovering together, investigating each technology in particular and then combining them, and deciding along the way whether it's worth it or not.
Although we won't come to an absolute conclusion, I invite you to join me on this journey of discovery.
What are Web Components?
Generally speaking, these are shareable and standalone pieces of code (HTML/CSS/JS) that offer visual style and interactivity and, if necessary, have an API for customization.
Web Components allow you to create those components without using a framework. It’s a suite of web platform APIs that are used together, allowing you to create new custom, reusable HTML tags with encapsulated styling and functionality and utilize them in your web apps.
Why use Web Components?
This is especially useful for micro frontend projects or big companies that use other platforms, providing a simple library of shared components for any project with any technology.
Web Components Specifications
There is a discrepancy regarding the technologies that make up Web Component specifications, the most widely accepted are Custom Elements, Shadow Dom, and HTML Templates, but I would like to add a fourth to that triumvirate, ES Module.
The only mandatory technology is Custom Elements, and you can pick the ones that best suit your requirements.
Custom Elements, defined in the HTML Living Standard Specification
Shadow DOM, defined in the DOM Living Standard Specification
HTML Templates, defined in the HTML Living Standard Specification
ES Modules, defined in ECMAScript Language Specification
Custom Elements are a vital feature, the core one to me, of Web Components, as their name implies, are HTML elements, like <form>, <div>, <button>, but something you can name yourself. They allow you to create your custom HTML tag with their behavior, properties, and methods and can be shared across frameworks and browsers.
With that done, you must register the custom element using the CustomElementRegistry.define() method. This method takes arguments.
A string representing the name you are giving to the element; note that custom element names must have at least one hyphen (kebab-case); they can’t be single words, to never clash with elements officially supported in the HTML specification.
A class that defines the behavior of the element.
(Optional) An options object containing an extends property specifies the built-in your element inherits from if any (only necessary when you are extending a built-in element).
Now you can use your custom element on your page like any other HTML tag.
This shadow DOM starts with a shadow root which you can attach any element in the same way as the light DOM; its elements are not visible to querySelector from the document object, so you can use the same id for an element inside the shadow DOM that it’s using for a component in the light DOM without conflict.
Also, shadow DOM has its stylesheets, styles rules from the other DOM are not applied.
You can attach a shadow root to any element using the Element.attachShadow() method. This takes as its parameter an options object that contains one option, mode, with the value of “open” or “closed.”
Note that still are two separate DOM (shadow and light), but you can access from the light DOM to the shadow DOM elements.
A shadow root can include content from its containing document using the <slot> tag. Using slots, you can put content from the outer document in designated spots in your shadow root.
A <template> contains an HTML fragment you can access using the content property, a read-only DocumentFragment containing the DOM subtree the template represents.
Just keep in mind that if you use the content property directly, the template will empty after appending, so the next time you try to append will just add empty contents.
To avoid this, you should clone or import it using cloneNode or importNode.
You can define variables, classes, or functions and decide which will be available from other modules; oppositely, you can import those from other modules and use them.
All major browsers support modules import now, then you don’t need a bundler, preprocessor, or transpiler, you just must tell the browser that a script should be treated as a module by using script type=”module”
The one that wasn't meant to be
Originally, HTML import was meant to be one of the APIs of Web Components, a technology developed by Google (and shipped to Chrome at some moment but not supported anymore), but that concept was never adopted as a standard; the other browser vendors had no plans to ship the feature.
To sum up
In this article, we introduced Web Components and overviewed the APIs we can use to craft Web Components.
In subsequent articles, we will take a deep dive into each of them, its features, use cases, and how to use them in the Web Components context (remember that these are web APIs whose use is not exclusive to Web Components, you can use them independently), to finalize combine all of them in our Web Component.