You can’t have growth without a little pain
My first introduction to Web Components was when my employer signed a new support client, a health care insurer in the southeastern United States. The site itself is a Drupal site, but the theme is filled with custom Web Components. Over 90 custom Web Components, to be clear.
Now, our team had never seen Web Components, had never worked on a site built with Web Components, so all of this was new to us. But, we jumped in. Our first challenge was when we were asked to build some new functionality for the site, and that’s when the pain began.
The Web Components on this site we are supporting are interrelated, so removing one had ripple effects on things that we never anticipated. Our level of effort to implement what should have been, on an ordinary Drupal site built with a Twig based theme, a day or two turned into over a week of building, testing, reviewing with QA, only to get back a whole list of items that were now not functioning properly, so wash rinse and repeat.
While frustrating, this was also an enigma, and as such, piqued my interest. So, I made it my mission to learn as much as I could about this thing called Web Components.
What are Web Components?
Web Components have been around for a while. The spec was first introduced in 2012, but browser adoption has been slow. It is only in the last couple of years that Web Components became supported in all of the major browsers (Chrome, Firefox, Safari and Edge). Safari is still a bit of a holdout on certain aspects of the Web Components spec, but for the bulk of the spec, the browsers all have support.
Web Components allow you to write Javascript that willl in turn create custom HTML tags for use in website page markup. Web Components also allow you to create custom functionality in an encapsulated way, so that it doesn’t affect other parts of the page or site.
Web Components incorporate four distinct technologies that all have web browser specs, and are supported by all of the major browsers, that provide a full spectrum of functionality to allow a developer to create some rather complex funtional components that can be used on a website by simply including the component’s javascript in a script tag to load it, and the embedding the markup into the HTML page so that it renders along with the rest of the HTML markup. When the markup loads, the component’s functionality is triggered. For the front end developer that is using a custom Web Component, it can be as simple as including the tag in the markup of the page, once you’ve loaded the Web Component’s javascript.
The Technologies that make up Web Components
The technologies that provide the full spectrum of functionality that is commonly known as Web Components are:
Each of these technologies has a corresponding specification that guides the use of the functionality consistently across all browsers. This post provides a summary of the technologies, I’ll go into more detail on each in later posts.
Custom Elements[back to list]
The Custom Elements spec is the defining spec for custom Web Components. It encapsulates the guidelines for establishing the framework that ultimately was adopted by the browsers in a consistent and conforming way.
By defining a Custom Element following the spec, a developer can define a custom element’s full functionality and have confidence that it will operate consistenty in all of the major browsers.
Custom elements are defined in a declared class that extends HTMLElement, the interface that ultimately defines HTML markup tags.
Once defined, the custom element then has to be registered with the CustomElementRegistry in order for it to be recognized as a valid custom HTML element. Without this registration, it is simply inert, undefined markup.
Shadow DOM[back to list]
The Shadow DOM specification defines the technology that implements encapsulation in the DOM for custom Web Components.
A custom element is not required to implement Shadow DOM to be a valid custom element. However, to provide any level of significant custom functionality without inadvertenty affecting other elements in the DOM tree, Shadow DOM is the tooling used to do just that.
A custom element implements Shadow DOM by using the attachShadow()
method, and passing in a required JSON element that defines the mode of the Shadow DOM. An element’s shadow DOM can be “open” or “closed”. Elements with an “open” shadow DOM allow access from outside the element via the shadowRoot
property; elements with a “closed” shadow DOM do not.
HTML Templates[back to list]
HTML Templates provide a way to add structured HTML markup to your rendered component in a consistent and repeatable fashion. The HTML Template spec exists and is usable outside of Web Components, but the addition and use of HTML Templates coupled with Shadow DOM provides a way to define an expected structure to the output generated by a Web Component. An HTML Template is defined by wrapping your markup in a <template>
tag, and then subsequently attaching it to the Shadow DOM of the Web Component.
Added flexibility for HTML Templates comes into play with the use of the <slot>
element, which is part of the Shadow DOM API. A <slot>
is a placeholder element that can be used to “inject” content into your <template>
. That “content” can include HTML Markup, which means the author of the HTML page can utilize a component and provide their own “flavor” of content to be displayed by that component that meet their specific needs. Unlike markup that is added to a Web Component inside the element’s class definition, content that is “slotted” into a component exists outside of the component, i.e. it is not encapsulated within the Web Component, and therefore can be styled with CSS outside of the Web Component itself.
ES Modules[back to list]
The ES Module spec governs the use of Javascript documents within other Javascript documents in a consistent manner. Within the realm of Web Components, ES Modules provide a way to allow reusability of Javascript existing outside the component within the definition of the Web Component itself. This opens up all sorts of possibilities for making Web Components infinitely more useful. One such possibility is making a Web Component’s code reusable, i.e. defining a base Web Component that can be extended to create other Web Component’s whose base functionality is similar.
It’s all about adherance to the DRY principle.
Wrap Up
This post is intended to be a high-level overview of Web Components. In later posts I’ll break down a practical example of a Web Component into it’s functional pieces, with each post focusing on a particular element of the Web Components ecosystem.