Web Components — Bringing Strong Encapsulation and Re-usability to the Client-side Elements
Addressing the unanswered question of building components that work everywhere with every framework 😎
Tech companies still have decades-old back-ends and services written in Java and C++, but their front-ends are changing too often. Although the change is inevitable in the software industry, teams can be more productive if they can stop re-inventing the wheel each time they:
- move to a new framework
- share the UI components with other teams in the company
🙄 [ Recall the bitter memories of moving to Angular2/React/Ember/Vue from AngularJS, or your team’s daily efforts to ship the same look and feel to the entire product stack in your company. ]
Today large organizations build pattern libraries, internal UI frameworks, and widget sets to share the consistent look and feel of software across the multiple teams inside a company. With the years of expertise, companies now have got used to this workaround. But workarounds don’t work when:
- Supporting multiple frameworks — The UI widget library that you build for your Vaadin front-ends will not work with your Angular/React front-ends. In large organizations, teams often use frameworks of their choice based on their business cases and pattern libraries will not work for them.
- Writing components in pure HTML/CSS/JS — Building everything in pure form provides us a great flexibility to use our library with most of the client-side technologies. But this requires lots of code lines, expertise, and developer hours.
Yeah, that sounds like a plan to bring the famous design concept, Componentization to our solution domain. In 2014, with a new set of web standards defined by W3C, browser vendors and developer advocates started to make this miracle happen. ‘Web Components’ was the name they gave to their solution.
🎉 Web Components — Strong Encapsulation for Web UIs
Some of these concepts can sound very alien to you. Therefore, let’s explore the underlying implementations that make web components a success. At the end of this article, we can connect all dots 😎
Did you visit Youtube recently? Did you like its new look? We have something to study there.
Observation #1 — Custom Elements
Do you see that the Youtube is using a new set of HTML tags that we haven’t seen before? Now few questions will come into your mind — “is it a standard practice?”, “can I do the same?”, “can I reuse them?” (Yes, Yes, and Yes 😇)
These strange HTML tags with names separated by dash (kebab-case) are called Custom Elements and their role is defined in the W3C web standards.
Although the existing HTML tag collection is very limited, with custom components, you can bundle up new behaviors and build unlimited number of new HTML tags with new features. Since each custom element works like a standard HTML component and conforms to the web’s built-in component model, you won’t notice any difference in them. Custom Elements offer modular implementations with less code and re-usability to the web design world.
Observation #2 — Shadow DOM
Shadow DOM is another web standard defined by W3C. If you carefully check the sources of web pages, you will notice a special code line —
Shadow DOM can inject a sub-tree of elements into the rendering of a document (elements inside this sub-tree are not the members of your main document’s DOM tree). This feature offers markup encapsulation to our component. The HTML and CSS code that go inside a shadow DOM are not exposed to the main DOM, so you will no longer need to worry about CSS leaks and naming conventions.
Shadow DOM is designed as a tool for building component-based apps. Therefore, it brings solutions for common problems in web development:
Isolated DOM: A component’s DOM is self-contained (e.g.
document.querySelector()won't return nodes in the component's shadow DOM).
Scoped CSS: CSS defined inside shadow DOM is scoped to it. Style rules don’t leak out and page styles don’t bleed in.
Composition: Design a declarative, markup-based API for your component.
Simplifies CSS — Scoped DOM means you can use simple CSS selectors, more generic id/class names, and not worry about naming conflicts.
Productivity — Think of apps in chunks of DOM rather than one large (global) page.
Custom Elements and Shadow DOM are the 2 major enablers for creating self-contained components.
If you use ES6 Modules, you can scope your JS code too. With that, you will no longer need to worry about JS scoping.
There are 2 implementations from HTML world that make the above-mentioned DOM manipulations possible:
Defined by W3C, HTML Imports provides a declarative way to load HTML resources into a document.
.htmlfile can contain. In other words, this makes imports a fantastic tool for loading related HTML/CSS/JS.
Defined in WhatWG specification, HTML Templates allow us to declare fragments of markup that go unused at page load, but can be instantiated later on at runtime. This is an essential part when it comes to creating Shadow DOM.
Wrapping content in a
<template>gives us few important properties.
Its content is effectively inert until activated. Essentially, your markup is hidden DOM and does not render.
Any content within a template won’t have side effects. Script doesn’t run, images don’t load, audio doesn’t play,…until the template is used.
Content is considered not to be in the document. Using
querySelector()in the main page won't return child nodes of a template.
Templates can be placed anywhere inside of
<frameset>and can contain any type of content which is allowed in those elements. Note that "anywhere" means that
<template>can safely be used in places that the HTML parser disallows...all but content model children. It can also be placed as a child of
Custom Elements, Shadow DOM, HTML Imports, and HTML Templates — these four specifications together form a platform for developers to build strongly-encapsulated reusable web components.
Libraries for building web components
- Bosonic is a collection of components designed to meet the everyday needs of web developers.
- Polymer provides a set of features for creating custom elements.
- Slim.js is an opensource lightweight web component library that provides data-binding and extended capabilities for components, using es6 native class inheritance.
- Stencil is an opensource compiler that generates standards-compliant web components.
When all of above libraries provide different features for us to play with web components, for large scale enterprises, I recommend using Polymer. It is a project backed by Google and has a rapidly-growing community and a promising future too.
While modern browsers are natively supporting the Web Component standards, other browsers use polyfills to support web components in an emulated environment. The trouble-maker is IE11 😑. For the enterprises with a large IE11 client base, web components may not be the best fit because you can’t enjoy the best of web components while continuing the IE11 support (sluggish performance). However, Shadow DOM v1 and Custom Elements v1 specs guarantee consistent browser support for web components in long run. Therefore, sooner or later, all browser vendors will have to ship the conformity to these standards.
Integrating web components with the existing systems is super easy. If you know the attributes, properties, and event APIs used inside a web component, you can implement the interactions for the component very easily. Also, you can use the web components with any client-side framework of your choice.
“I don’t care whether you’re Angular or React. If you’re nice to me, I’ll be nice to you. Simple as that.“ — a web component
So this is all about the building blocks of modern web in a nutshell. We went from the practical issues in pattern libraries to creating Custom Elements to encapsulating UI elements inside Shadow DOM to checking libraries, browser support, and framework integration too. Definitely a lot of moving pieces here, especially for beginners. I admit the fact that nowadays client-side programming can be quite daunting for anyone. That is exactly why I recommend you to look at the possibilities of using web components to save your investments on building the same stuff again and again. Just create the most used components in your product stack with web components and drop these components in every web application that requires them. Just stop re-inventing the wheel and let your teams focus more on business logic and accelerate the development!
If you need evidence, most of the enterprises in the world embrace this encapsulated reusable component concept and use different flavors of web component specifications to reduce the time spending on re-inventing user experiences that already exist. Google products, Chrome team, Youtube, McDonald’s, Coca-cola, ING, GE, Net-a-Porter, USA Today, EA, Bloomberg, Comcast, Salesforce, Victoria’s Secret, BBVA, Dominos Pizza, Github, Vaadin, and so many companies currently use web components in their production.
It’s an exciting time to try out web components, and I hope this information can serve as a knowledge sharing piece. I personally love using Polymer (web component library + app framework) and within next few days, I will reveal more insights in this channel. In the meantime, I invite you to research more on the topic and get yourselves updated on this new hype! 😏
- Building Components — Google Developers
- Custom Elements v1: allows authors to define their own custom tags (spec, tutorial).
- HTML Imports: a way to include and reuse HTML documents via other HTML documents (spec, tutorial).
- Shadow DOM v1: provides encapsulation by hiding DOM subtrees under shadow roots (spec, tutorial).
- Learning Web Components — Joe Marini (Lynda.com)
- GE Predix Design System (story, library)
- EA — Building UI at Enterprise Scale with Web Components (Polymer Summit 2017)