|||

Video Transcript

X

Building with Web Components

In the early years of web development, there were three standard fundamentals upon which every website was built: HTML, CSS, and JavaScript. As time passed, web developers became more proficient in their construction of fancy UI/UX widgets for websites. With the need for newer ways of crafting a site coming in conflict with the relatively slow adoption of newer standards, more and more developers began to build their own libraries to abstract away some of the technical details. The web ceased being a standard: now your website could be a React site, or an Angular site, or a Vue site, or any number of other web framework that are not interoperable with each other.

Web components seek to tilt the balance of web development back towards a standard agreed upon by browser vendors and developers. Various polyfills and proprietary frameworks have achieved what web components are now trying to standardize: composable units of JavaScript and HTML that can be imported and reused across web applications. Let's explore the history of web components and the advantages they provide over third-party libraries.

How it all began

After some attempts by browser vendors to create a standard—and subsequent slow progress—front-end developers realized it was up to them to create a browser-agnostic library delivering on the promise of the web components vision. When React was released, it completely changed the paradigm of web development in two key ways. First, with a bit of JavaScript and some XML-like syntax, React allowed you to compose custom HTML tags it called components:

class HelloMessage extends React.Component {
  render() {
    return (
    <h1>
        Hello <span class="name">{this.props.name}</span>
    </h1>
    );
  }
}

ReactDOM.render(
  <HelloMessage name="Johnny" />,
  document.getElementById('hello-example-container')
);

This trivial example shows how you can encapsulate logic to create React components which can be reused across your app and shared with other developers.

Second, React popularized the concept of a virtual DOM. The DOM is your entire HTML document, all the HTML tags that a browser slurps up to render a website. However, the relationship between HTML tags, JavaScript, and CSS which make up a website is rather fragile. Making changes to one component could inadvertently affect other aspects of the site. One of the benefits of the virtual DOM was to make sure that UI updates only redrew specific chunks of HTML through JavaScript events. Thus, developers could easily build websites rendering massive amounts of changing data without necessarily worrying about the performance implications.

Around 2015, Google began developing the Polymer Project as a means of demonstrating how they wanted web standards to evolve through polyfills. Over the years and various releases, the ideas presented by Polymer library began to be incorporated by the W3C for standardization and browser adoption. The work started back in 2012 by the W3C (and originally introduced by Alex Russell at Fronteers Conference 2011) began to get more attention, undergoing various design changes to address developers' concerns.

The web components toolkit

Let's take a look at the web standards which make up web components today.

Custom elements

Custom elements allows you to create custom HTML tags which can exhibit any JavaScript behavior:

class SayHello extends HTMLElement {
  constructor() {
    super();

    let p = document.createElement(“p”);
    let text = document.createTextNode(“Hello world!”);
    p.appendChild(text);

    this.appendChild(p);
  }
}

customElements.define('say-hello', SayHello);

Custom elements can be used to encapsulate logic across your site and reused wherever necessary. Since they're a web standard, you won't need to load an additional JavaScript framework to support them.

HTML templates

If you need to reuse markup on a website, it can be helpful to make use of an HTML template. HTML templates are ignored by the browser until they are called upon to be rendered. Thus, you can create complicated blocks of HTML and render them instantaneously via JavaScript.

To create an HTML template, all you need to do is wrap up your HTML with the new <template> tag:

<template id="template">
  <script>
    const button = document.getElementById('click-button');
    button.addEventListener('click', event => alert(event));
  </script>
  <style>
    #click-button {
    border: 0;
    border-radius: 4px;
    color: white;
    font-size: 1.5rem;
    padding: .5rem 1rem;
    }
  </style>
  <button id="click-button">Click Me!</button>
</template>

Shadow DOM

The shadow DOM is another concept which provides support for further web page encapsulation. Any elements within the shadow DOM are not affected by the CSS styles of any other markup on the page, and similarly, any CSS defined within the shadow DOM doesn't affect other elements. They can also be configured to not be affected by external JavaScript, either. Among other advantages, this results in lower memory usage for the browser and faster render times. If it's helpful, you can think of elements in the shadow DOM as more secure iframes.

To add an element to the shadow DOM, you call attachShadow() on it:

class MyWebComponent extends HTMLElement {
    constructor() {
        super();
        this.attachShadow({ mode: "open" });
    }
    connectedCallback() {
        this.shadowRoot.innerHTML = `
            <p>I'm in the Shadow Root!</p>
        `;
    }
}

window.customElements.define("my-web-component", MyWebComponent);

This creates a custom element, <my-web-component>, whose p tag would not be affected by any other styles on the page.

Web component ecosystems

The greatest advantage web components have over using a library is their ability to provide standards-compliant, composable HTML elements. What this means is that if you have built a web component, you can package it up as a release for other developers to consume as a dependency in their project, just like any other Node or Ruby package, and those developers can be assured that that web component will work across all (well, most) web browsers without requiring the browser to load a front-end framework like React, Angular, or Vue.

To give an example, Shader Doodle is a custom element which sets up the ability to easily create fragment shaders. Developers who need this functionality can just fetch the package and insert it as a <shader-doodle> tag in their HTML, rather than creating the functionality of Share Doodle from scratch.

Now, with the great interoperability that web components give you, many frameworks and libraries like Vue or React have started to provide the option to generate web components out of their proprietary code. That way you don't have to learn all the low-level APIs of the aforementioned standards, and can instead focus on coding. There many other libraries for creating web components, like Polymer, X-Tag, slim.js, Riot.js, and Stencil.

Another great example of this are Salesforce’s Lightning Web Components, a lightweight framework that abstracts away the complexity of the different web standards. It provides a standards-compliant foundation for building web components which can be used in any project.

Getting more involved web components

We recorded an episode of Code[ish], our podcast on all things tech, that meticulously went through the history (and future!) of web components. Be sure to check out that interview from someone who literally wrote the book on web components.

You can also join the Polymer Slack workspace to chat with other web developers about working with these standards.

Originally published: March 04, 2020

Browse the archives for engineering or all blogs Subscribe to the RSS feed for engineering or all blogs.