Web Components have come to stay, and this is what you need to know

José Manuel García (a.k.a. Sema)
gft-engineering
Published in
13 min readApr 15, 2021

Nowadays, almost everyone has interacted in one or another way with the web: from older people slowly and methodically opening their missed call list to babies of a few months throwing their fingers against a mobile screen without fear, touching up to the last pixel of that display full of colours and shapes that attract them.

We are all used to seeing buttons, images, videos and texts in a wide variety of arrangements (paragraphs, tables, list, etc.). Any element we see on the web consists of one or more basic components, which can form more complex structures if we group them or make them collaborate with each other.

As developers, (and if you are reading this article, you are probably related to the software world in one or another way), we want to write robust, maintainable, efficient… and reusable code! How many times have we had to develop some pieces, structures or elements that were very similar to a previous one we already developed?

Re-usability is the concept (besides a development best practice) that prevent us to write again and again those repetitive code snippets between applications with just a few changes (such as a color, among others), which becomes a waste of time and a greater amount of code to be maintained. Unfortunately, despite of “copy & paste”, it’s not guaranteed the visual coherence between apps for those duplicated frontend parts.

When a customer is quite large, another best practice is the definition of an UI library from UX department to govern all visual matters. Among other advantages, it facilitates reuse and homogenisation across all customer’s projects (and this concept has evolved towards to Design Systems, but this topic will be introduced later). A problem will arise if, for whatever reason, it is necessary to change the framework or if a project needs to be developed with a different one…

Uhm, did someone say “rewrite the entire UI library”? Probably…

The foundations of any UI library…

However, the solution of a complete re-implementation is just not acceptable.

Let me travel briefly, during this paragraph, over 20 years ago. When the web was younger, each browser understood the web on its own manner. The hardened developer community needed to develop for one of them (ejem… Internet Explorer, ejem…), and later, adapt it to the rest of browsers, crossing their fingers and hoping to not to spend so much additional (and weird) time. What was the problem? Our code had to be adapted to different browsers because they supported the standard (JavaScript) in different ways, so, our apps were more or less coupled to the browsers we wanted to support; the apps were not cross-browser. Furthermore, a bad technical design could mix business logic with cross-browser-javascript-logic. Nowadays, fortunately, JavaScript ecosystem has evolved a lot, and now it’s a reality the full adoption of new features (like WebWorkers or Custom Elements among others) for all major browsers.

Once solved the original problem… we faced another one, but in a higher abstraction layer: the framework’s war. All of our web components are traditionally developed or written on AngularJS, Angular, React, Vue… or any other valid option from a large list of candidates. What’s the new scenario? Now, our apps are not tied to a browser… but instead they’re to a framework! Why we need to rewrite again and again a button for each project (or… ehem… “copy & paste” them!)? I think… that’s the moment for an emergency call to the Fantastic Four!

Fantastic Four to the coding-rescue! … Or not?

No, no!! They are not the FF to which I am referring to… These are:

They appeared -among others- to solve some recurrent problems: isolation or component’s re-usability between different frameworks… and thanks to the combination of four standard technologies, Web Components emerged. The collaboration of these fantastic four allow us to create reusable components without fear of variable collisions, since they have their own logic and/or encapsulated visual styles, being agnostic to any web framework (if the browsers support them or using some polyfill otherwise). The pure Web Components can even run directly into the browser without any library/framework, just the standard (for all major browsers who supports ES6) because they leverage the technology natively provided by the browser.

The Web Component’s standards

And which are these -fantastic- four technologies we’ve introduced before?

  • Custom Elements: they give developers the ability to extend HTML and create their own tags because nowadays, the native ones are not enough for our frontend apps. They benefit from the Web’s built-in component model. The result is a more modular code that can be reused in many different contexts.
  • Shadow DOM: it offers component’s style and markup encapsulation. It is a critical behaviour of the Web Components because it ensures that a component will work in any environment even if other CSS or JavaScript code is running on the page.
  • HTML Templates: they are inert fragments of HTML that will be reused in the application, for instance, to create a table row or a modal window. The main benefit is that its DOM will not be rendered by the browser, but it can be referred from JavaScript to operate with it. Once the content of the template is inserted into the DOM, the content will be rendered.
  • HTML Imports: Web Components are traditionally written in HTML, and this technology was used to import these definition files into the main application for using them into the app. This mechanism is very similar than CSS stylesheet link-rel imports. However, a better and powerful approach was proposed (besides the HTML Import never passed the draft phase), and finally implemented as the new way for importing Web Components’ definition: ES Imports. ES Imports is the new way is to use ES6’s import instruction, where the main benefit is the isolation of global elements defined into a module. In order to use an element defined outside of a module, it needs to be exported first. In Web Component’s context, the ES6 modules will host each Web Component’s definition.

We’ve just talked about browsers and compatibility… What is the current support’s state? Could we write and develop Web Components without any constraints or limitations?

From January 15th, Microsoft’s Edge browser implements open-source Chromium project, therefore, Edge is now totally compatible with web standards, which is a huge good news for everybody, not just for developers community, but since regular users too.

Vanilla components: pure & native

As we previously said, Web Components are totally supported by major browsers (or even some older version with the help of polyfills). So, a Web Component could be written in just plain JavaScript in few steps:

  1. Creating a class, where the Web Component’s logic (business or presentational) will be placed. If component is visual, it will need some kind of HTML. Moreover, the component could set event listeners, not necessarily related to UI-events.
  2. Registering the new component, binding or linking its new tag name with the class definition (remember, class definition, not an instance of it).

Obviously, the first step will be the one most repeated by a developer: the boilerplate code needed to scaffold our components. Since we are writing them in plain JavaScript, we need to perform some tasks manually (like an artisan).

Image source

For instance, this could be a typical “Hello World” example:

The template used by previous Web Component:

With the previous snippets, we will be able to used it anywhere:

Visually, the result is the following:

Our WebComponent rendered… simple and easy :-)

Which is the result of this (Web Component instantiation through <my-web-component> tag):

It’s very important to notice that Web Components’ name have to include a hyphen in its name (it means that name has to contain at least two words). This is to avoid possible collisions with HTML5 standard tag names (such as img, input, table…).

When the browser renders the HTML and encounters our custom tag “my-web-component” searches in the registry in order to use its corresponding class and create a new instance. If none is found, then the engine will ignore it.

We can see some repetitive actions (e.g.: defining styles, template declaration, attach shadow DOM…) that they are very repetitive and manual. If it’s repetitive and manual, this could be improved and simplified. How? Using a tiny abstraction layer where those tasks and details will be encapsulated and hidden for the developers. This tiny layer could be called “Web Component library” in order to help us defining and creating our Web Components (among other responsibilities), which will be the building blocks for our applications.

Better with a library

As we previously introduced, we don’t want to waste time and effort. But, which alternatives we have? Which libraries are out there that worth to be mentioned and considered?

Image sources: here and here

Main most well-known libraries:

  • LitElement: a simple base class for creating fast, lightweight web components (it’s the sucessor of Polymer library).
  • Angular elements: this library allows developers to package Angular components as custom elements.
  • Hybrids: UI library for creating web components with unique declarative and functional approach based on plan objects and pure functions.
  • SlimJS: lightweight web component authoring library that provides extended capabilities for components (such as data binding) using ES6 native class inheritance.
  • SvelteJS: is a radical new approach to building user interfaces.
  • SkateJS: is a functional reactive abstraction over the web components standard as a set of packages that enables developers to write small, fast and scalable web components using popular view libraries (such as Preact or LitHTML).
  • StencilJS: is a toolchain for building reusable, scalable Design Systems generating small, blazing bast and 100% standard based Web Components.

As additional comment, we will show another interesting and widespread topic: scaffolding’s size. The following image compares the “verbosity” of each library, which is related to the syntax used:

Image source

Obviously, the pure plain JavaScript approach has the longest code since it’s written without the help of a library, but it gives us an idea of the effort needed to obtain the same result, the abstraction offered by those libraries and the amount of code that we’d need to maintain.

In further articles of our frontend series we’ll go deeper in some of them, stay tuned!

Are Web Components compatible with the main frameworks?

OK, you are decided to push out into the Web Component’s world… Great! Good choice! But, what degree of compatibility with major frameworks do they offer?

Image source

Each application is like a puzzle (a set of different pieces working together). Each puzzle is typically a framework (a framework chosen for developing the app). Each application has its own components which are framework-specific (therefore, an Angular component won’t be used inside a React app directly -or vice versa-). In this analogy, we can understand that a piece of a puzzle can’t be imported into another puzzle unless we perform some “adaption tasks”.

As we said, Web Components don’t need a specific framework to be used, and the browsers understand them directly without problem. Browser’s engine is the responsible for rendering them. For a framework point of view, a Web Component is like any other HTML standard component: some artefact defined by a third-entity, such as other company team -like architecture team-, an open source project released by a company, the own community, etc.

The integration between framework and web component it’s technologically possible.

Moreover, the Web Components can be (re)used and can interoperate with any application (and even with any framework) if the communication is made according to some principles:

A framework component is be able to interact with a web component through its properties, attributes and public methods.

Input: data flow goes from the parent (framework component) to its child (web component).

A web component is be able to interact with an ancestor framework component through standard events.

We have two possibilities to listen those events (actions) from child component.

Output: data flow goes from the child (web component) to the parent.
OPTION A: “standard way”
OPTION B: “Angular way” (framework used in this example)

These inputs and outputs represent the public API of a Web Component.

This behaviour is the basis of a modern web event-driven architecture (EDA). However, there are situations that the integration is not fully supported. In order to check the peculiarities of each framework, you can check custom-elements-everywhere.

Web Components are not just a developer matter

In almost every project, the workflow for designing and developing a new app started by the UX team. They gather the requirements of the customers and model its needs, transforming them into a beautiful, usable and accessible UI for the users. For a long time, they create an Adobe Photoshop project and “draw” there the screens and flows in that canvas. After that, a simply export to PDF generated the input file for the dev team. That short and simple guideline should express all the flows, alternative cases, component interactions…

Image source

Unfortunately, there was a huge gap between those worlds: UX & Devs, because they understand the same concept from different points of view, with different representations and terms. The abstractions are different for each team. Obviously, each one has its own peculiarities, but between them, there is some overlapping, which could be a source of problems and misunderstandings.

Image source

Therefore, the need of a common “language”, represented by a design spec or a library of reusable components that could be shared across the company (at the same way as Web Components are reused), gets more importance. This Design System is much more than a static PDF, and thus, we’ll go deeper in that approach in our series of articles about DSs (so, get in touch!).

The parts of an UI are those portions (more or less complex) which have importance by themselves, because they are well-known recognized entities, with a certain responsibility. These elemental pieces -such as buttons or icons- can be working together (composition) for building more complex components (card):

All of these components (basic and complex) will become in the building blocks for all enterprise projects, ensuring the brand consistency since all developers will use the same components, no matter which framework use its project.

The main benefit of a dev team focused on this component library is that all changes will be centralized, coordinated with UX/UI team, and properly managed to evolve them. Many of these libraries are designed, developed and released by important and relevant companies. Next, some references (not necessary of tech enterprises), publicly available (an extended list can be checked here):

In the case of software enterprises (such as IBM, Salesforce or Microsoft among many others), when they offer and publish its Design System guidelines, they pursue a double goal:

  • Make its brand more recognisable through the patterns, elements, colours and shapes.
  • Ensure the fidelity and visual coherence across the entire ecosystem, specially on external apps developed by independent companies or developers (for instance, those who write a Salesforce module, a Microsoft Store app, etc.) that it would be integrated in its platforms.

Another advantage of a component library is that we can explore all the options of a component -also known as variations-, when we can see the behaviour. If we think of a button, we could check how it behaves when is enabled, disabled, hovered, selected, focused, active, primary, secondary, accent… and all of these properties are just for one component. Can you imagine all the possibilities of the whole component’s catalog?

Moreover, publishing the catalog (even just for internal use only), allows to the whole company to check the building blocks available with its interactions, current specs, variations… and detect possible gaps or new features. All UX/UI designers will use just those elements to design new apps (through a design library/app, like Sketch or Figma, among others).

At the same time, this component library is more stable and less dependent because it’s a separated project itself, with its own quality metrics, checks, pipelines and releases. Of course, the documentation is also covered in this approach by many emerging tools. Those tools come for build that component’s catalog before-mentioned like a demo viewer, but also for checking the component’s public API as a playground or showcase. One example of them:

Image source

Conclusions

The Web Components have come to stay, this it’s obvious due to its growth in last years, as well as its evolution, maturity and framework integration possibilities (thanks to web standards).

We can summarize the key points we’ve discussed through the article in two type of benefits:

Brief benefits table

However, there are still some painful topics:

  • Accessibility and indexability, due to own encapsulation (shadow DOM), which it’s a great benefit but also a problem in some edge cases.
  • There are still some difficulties to SSR (server-side rendering) with Web Components, due to the shadow DOM and pre-render it on server-side. Nonetheless, some Web Component library are releasing tools for this feature, but there is still a lot of work to do.
  • Browser’s support: all major browsers already support the Web Components’ standard, but some older version of someone could not have a total support. For that gap, there are polyfills that help to increase the compatibility to avoid that the support could be a problem in its adoption or use.

Despite of these points, which should be solved sooner or later, the benefits and the adoption is unstoppable. The recommendation of native and pure Web Components can be narrowed to a sentence: Embrace the platform!

--

--

José Manuel García (a.k.a. Sema)
gft-engineering

Technology enthusiast, JavaScript lover and “Cordobéh”. Architect @ GFT Group