Web Components aren't a framework replacement - they're better than that
Sat Jan 18 2020
With the release of the Chromium based Edge browser, and Web Components now being available in all major browsers, it's worth taking a moment to discuss what Web Components are, what they are not, and how they relate to the established UI frameworks such as React, Vue, and Angular.
Identity problem
Web Components mean different things to different people. Officially they a group of 3 language features:
- Custom Elements - a set of APIs to create new HTML elements
- Shadow DOM - the ability to encapsulate both the DOM and styling inside an element
- HTML Templates - a way of creating DOM independent of the current document
While this grouping makes sense in that all three can be used while creating Web Components, only Custom Elements themselves are required to create one.
Shadow DOM is a great addition to the web, but you can create Web Components without it (indeed you can even use Shadow DOM outside of Custom Elements, although I'm not sure why you'd want to).
Similarly HTML Templates can be used with Web Components but are by no means necessary, and have a wider use outside of Web Components. For these reasons I prefer to think of Web Components as Custom Elements only, and refer to the Shadow DOM and/or HTML Templates explicitly when used.
For the remainder of this post the term Web Components (WC) will refer to Custom Elements.
Building blocks
Let's consider what Web Components are trying to achieve. As part of the extensible web their aim is to provide a basic building block for the web on top of which extra functionality can be added by developers as and when needed. The most fundamental building block of any web site or application are the HTML elements themselves. Built in elements encapsulate their functionality and styling independent of other elements on the page.
WC provide developers with the ability to create their own HTML elements that behave in exactly the same way as native elements, and can be manipulated with the same native DOM APIs in the browser. As such you can:
Use a WC in a site developed 10 years ago with jQuery.
Re-use a WC internally in a variety of frameworks.
Use a WC developed today in 5 years time with the latest framework.
Use a WC in a simple HTML page with no framework or library.
What's in the box
In common with the frameworks, WC provide:
- Component model - a way of encapsulating the functional behaviour of the component
- Component lifecycle - methods that can be used to control the behaviour of the component when it's added, removed and updated.
In addition WC uniquely provide:
- Style and content encapsulation - through the (optional) use of Shadow DOM the internals of the WC can be styled independently of the containing document. CSS rules are scoped to the element so the element will not inherit unwanted styling from the outside, and
id
s andclasses
and any other attributes are scoped to the component. - Interoperability - because they are true HTML elements they they can be used anywhere HTML is expected and are entirely interoperable with past, current and future libraries that deal with HTML elements directly. See Custom Elements Everywhere for full list of interoperable frameworks.
- Native implementation - WC are provided built-in to the browser, so there are no 3rd party sources to load, parse, update, or maintain, and no build steps to incorporate. This makes them performant by default.
The missing parts
What WC don't provide, but frameworks do, is any model for:
- Managing component state
- Reactivity - updating of the component when that state changes
- Declarative templating for non-string properties
- Server side rendering (SSR) - enabling the component to be fully rendered on the server as sent as a string to the browser so that it can be displayed (although not fully functional) without JavaScript.
The first two of these features are seen as key to writing modern day web apps, and rightly so - handling state and updating elements manually can quickly become cumbersome as the complexity of the app increases.
Declarative templating is a harder comparison to make - while string properties (or more correctly attributes) can be set declaratively, e.g.:
<x-component description="Product"></x-component>
non-string properties (Number, Object, Function etc.) must be set in JavaScript. This is due to the nature of HTML itself - being a markup language there is no way to define non-string properties.
Server side rendering is also more complicated. WC can be rendered on the server since they are just written as HTML elements, but WC making use of the Shadow DOM cannot be without making use of a server side DOM implementation. Even then workarounds must be found to apply styling since the Shadow DOM style is only applied once the component has been instantiated in JavaScript. A declarative Shadow DOM would solve this issue, but that seems some way off at this point, if at all. However with search engines now able to crawl Shadow DOM, and a potential performance cost (sending the component twice, once as an SSR string and again in the component definition) the necessity of SSR may be less important.
The conclusion often made from this is that WC are only suited to being leaf nodes - small self contained elements that are included inside larger more complex apps - and are not suited to being used for building the apps themselves.
A third way
So WC alone are not a replacement for a framework - but they were never intended to be. By their very nature they provide a native, interoperable base on top of which developers can add further functionality if required. In the simplest cases they can be used as-is to build small, performant, re-usable components, but there's nothing to stop component authors adding state management, reactiveness, declaritive templating and more when the need arises. Indeed there are already several well established libraries that enable this functionality to be applied to WC such as lit-html and lit-element.
Indeed having the flexibility to choose when and how these features are integrated in to your component can be seen as an advantage too. They become an implementation detail that can be changed as and when necessary, and because their interface remains the standard HTML element no change is needed in the way they are used whatever the internal details.
Summary
So it's clear that when deciding to use Web Components, it's not a direct choice between them and a framework.
Existing frameworks provide an all in one solution to building web UIs, but they do so at the expense of locking component authors into their particular implementations and eco-systems. This results in components that are not interoperable or re-usable outside of the chosen framework.
On the other hand native Web Components are fully interoperable and re-usable both inside and outside of existing frameworks and anywhere HTML is used, whilst not providing everything that might be needed to write a complex web app. These 'missing parts' however can be provided quite easily with existing libraries as and when needed, and as Web Components become more popular the range of options to add this functionality will only increase.