Web Components

Getting Started with Web Components – a Beginners Guide

Web Components

What are web components?

Technology keeps changing every day, and the growth of the web is something we can all witness directly through millions of devices that can connect to the internet.

Decades ago, front-end development only involved simple tech stacks to deliver user interfaces. This method wasn’t as efficient because front-end developers could not reuse elements. Further advancements in browser engines and front-end development led to the introduction of a new advanced stack called Web Components.

Web Components are a set of features for delivering high-quality user experiences through standard components that are reusable, allowing for encapsulation and interoperability of individual HTML elements.

In this beginner’s guide, we will cover the basics of web components, their various specifications and how you can go about creating your own web components.

Components inside frameworks

Web Components are still a work in progress and many developers may not know about them since they are not getting as much publicity like frameworks.

Web components are native HTML elements; you do not need to install any front-end framework for you to use them. Front-end frameworks include React, Angular, Vue, and more; with each framework having its specific components. Since web components are interoperable, you can use them in any front-end framework; however, you cannot use a framework’s specific component inside another framework. For instance, you cannot use React components in an Angular application, and vice versa.

What are we trying to solve with web components?

Code reusability is a great idea for all development purposes; it reduces development time as well as development complexities. Web components bring code reusability in many places of a project and even other projects with a similar look and feel.

Modularity is a feature that allows separating and recombining system components to bring benefits such as flexibility and variety of uses. Functions and micro-services were introduced to bring about modularity in development of complex systems. It was about time that we had such features in front-end development, thus the introduction of web components.

Interoperability: Consider a scenario where you were previously working on an Angular app and have developed a unique date-picker element. Your current project requires you to use React.js. Wouldn’t it be great if you could import the Angular component into the React app? Unfortunately, it’s not possible, yet. But with Web components, this is possible since they are standard and can work in any browser, with any JavaScript framework or library.

Can you use web components now?

Yes. Web components are already being used by sites like YouTube, the top video platform of the web, so they are here to stay. What is more, you do not need any specific framework to implement components on your website, so do not worry if you don’t yet know React.js. Moreover, the Google Chrome dev team maintains a polyfill project called Polymer that outputs actual web components to help developers build a better web. Another similar project is Svelte UI components. There are opportunities for web components to grow as the developer community continues to work on more tools.

Browser compatibility

You probably have visited YouTube on your laptop, and it worked just fine, why so? Web Components work in all modern browsers including;

  • Google Chrome for Desktop
  • Google Chrome for Android
  • Mozilla Firefox
  • Apple Safari for MacBook
  • Mobile Safari for iPad and iPhone
  • Microsoft Edge

The main specifications of web components

There are four specifications for building web components:

  • HTML templates
  • Shadow DOM
  • ES Modules
  • Custom Elements

We will discuss with examples in this section.

HTML Templates

HTML templates are necessary for writing reusable code and defining the look and feel. Unless you are writing assembly code to execute on a microchip, in web development, we always start from somewhere, i.e. a template. If you have been using HTML, you understand the dozens of tags in HTML – <table>, <h1>, <p>, <title>, etc.

In web components, we have the <template> tag as the starting point. You can add markup code within the <template> tag which you can later use to define a page or element.

Here is a simple template defining a heading and a paragraph.

<template>
    <h1>Web Components</h1>
    <p>Web Components are awesome, don't you think?</p>
    <script>
        //add your scripts here
    </script>
</template>

The browser does not execute markup inside the <template> tag at page load. If you have tags inside the <template> calling external sources like <video>, <audio>, <img>, or <script> tags, they will not execute. Basically, the whole template itself shows nothing on initial page load until you activate it in the DOM using JavaScript, this brings us to the next specification.

Shadow DOM

In an earlier definition, we mentioned that web components give us encapsulation features – this is made possible by the Shadow DOM specification. It makes sure that the HTML and CSS markup of one element doesn’t affect other elements on a page. Shadow DOM can be called to render an element, for example, the HTML template described earlier is activated by a call from the Shadow DOM. To create a shadow DOM, you call its createShadowRoot method. It returns a document fragment that you can use to fill with content, as shown in the example below.

<div class="main"></div>

<script>
    var host = document.querySelector(‘.main’);
    var root = host.createShadowRoot();
    root.innerHTML = '<p> <strong>Web Components</strong> are awesome, what do you think?</p>'
</script>

Shadow DOM has a few elements under it;

  • Shadow Host is the one element visible to the user. It’s instantiated by the createShadowRoot method as seen in the code above. As the host, it holds other content and tags within it.
  • Shadow Root is a document fragment returned by the createShadowRoot method that we can fill with anything. While this part is not visible to the user, it is what the browser renders once it encounters the tag in the querySelector. In this case, the page initially loads with an empty div, and then we append some text using the <p> tag.
  • Shadow Boundary is an invisible barrier protecting the shadow root from the parent document. While the markup inside a component is encapsulated, the shadow boundary ensures CSS in the parent document doesn’t affect the markup inside the component. A component is independent, making it easier to be reused without worrying about its contents being affected by the parent.

For example, if you have specified ‘Arial’ font for the whole page, and then have a <p> in the shadow DOM with ‘Helvetica’ font; the rest of the content on the page will render with ‘Arial’ font, while any instance of the shadow DOM will render with Helvetica.

ES Modules

Some tutorials refer to them as HTML imports. To be more precise, HTML imports work with ES Modules. ES Module is the ECMAScript implementation for working with modules. HTML modules let you define web components in one file, then you can import into your project or reuse it on several other pages. It works by adding a <link> tag in an HTML document the same way you usually include CSS files, as shown below.

<link rel="import" href="myfile.html">

In this case, you have your web components defined in the myfile.html. You can use the same file on several pages and the look and feel of the components will remain as you had declared. As explained earlier these components will not render until you activate them in the DOM using JavaScript. Hence, if your file has many components, only those you choose to render on a certain page will display.  If the file you were importing had this line;

<div class="main"></div>

Then, here are the steps you will take to activate it;

<script>
    var link = document.querySelector('link[rel=import]');
    var div = link.import;
    // Access DOM of the document in /imports/myfile.html
    var main = div.querySelector('div .main');
</script>

A module can have several components, grouped together because they are related. You can break your code into several independent modules which you only import when you need them. It makes it easier to maintain your code.

Custom Elements

Custom Element allow you to create new HTML elements that you can add into the DOM. This is made possible through the Custom Elements API. Two parts of custom elements exist.

  • Autonomous custom elements – these are HTML elements create entirely using the Custom Elements API and are separate from native HTML elements.
  • Customized built-in elements – these are HTML elements built based on and reuses the functionality of native HTML elements.

Here is a code snippet showing how you declare a custom element.

<script>
    class AddText extends HTMLElement {
        constructor() {
            // Always call super first in constructor
            super();

            // Element functionality goes here
            //create the shadow root
            var host = this.attachShadow({mode: 'open'});

            //create a main div
            const div=document.createElement('div');
            div.setAttribute('class', 'main');

            //create a paragraph
            const p=document.createElement('p');
            p.textContent='Web Components are awesome, what do you think?';

            //create some styles
            const style=document.createElement('style');
            style.textContent=' p {color:blue;} ';

            host.appendChild(style);
            host.appendChild(div);
            div.appendChild(p);
        }
    }
//then you need to define it to make it available to the DOM
    customElements.define('add-text', AddText);
</script>

You can then use the custom element in your page as shown below, by simply adding one line;

<add-text></add-text>

If you ever wanted to create your own HTML elements, this is how you go about it. It’s worth noting that custom elements have their own lifecycle and you can define callbacks which fire based on the elements’ lifecycle.

How to Create your own web components

There are several tools for creating web components, they include using;  

  • Vanilla JavaScript
  • Polymer
  • Stencil

Using Vanilla JavaScript

Vanilla JavaScript is just plain JavaScript. In the above example, given under custom elements, we used plain JavaScript. For brevity purposes, we won’t repeat it here.

Polymer

Polymer is a Google Chrome team’s open source project for creating web components with a set of polyfills. Polymer takes care of the boilerplate code, allowing developers to focus on the logic of their apps. Polymer works with Webcomponent.js as its dependency and can be loaded in the web app to provide a suite of polyfills. While modern browsers already support web components, it’s good to consider those that don’t, and that’s how polyfills come into the picture. Basically, polyfills implement features on web browsers that may not be compatible with the feature.

The polyfills are imported into a project using the npm command;

 npm install — save @webcomponents/webcomponentsj

Polymer is imported into a project using the npm command;

 npm i @polymer/polymer

Here is a code snippet using polymer to create web components.

<script src="node_modules/@webcomponents/webcomponents-loader.js"></script>
<script type="module">
    import {PolymerElement, html} from '@polymer/polymer';

    class AddText extends PolymerElement {
        static get properties() { return { mood: String }}
        static get template() {
            return html`
          <style> .mood { color: blue; } </style>
          Web Components are awesomely <span class="mood">[[mood]]</span>!
        `;
        }
    }

    customElements.define('add-text', AddText);
</script>

<add-text mood="happy"></add-text>

The current stable version of Polymer is 3.0.

Stencil

Stencil is a library for building and compiling reusable web components. It combines features from the best frontend frameworks to generate web components instead of third-party component models. Stencil can create simple independent components or entire apps. You must have the latest Node.js installed; you initialize stencil by running the following command.

  npm init stencil

The command displays three starter packs to choose from: ionic-pwa, app, component.

This command is used to update Stencil;

 npm install @stencil/core@latest --save-exact

Stencil files are saved with .tsx extension. Here is a stencil code snippet;

<script>
    import { Component, Prop } from '@stencil/core';

    @Component({
        tag: 'add-text',
    })
    export class AddText {

        // Indicate that name should be a public property on the component
        @Prop() title: string;

        render() {
            return (
                <p>
                You have been reading about {this.title}
        </p>
        );
        }
    }
</script>

<add-text title="Web Components"></add-text>

Additional tools for creating web components include;

Example of web components in use today

A cool example that you are already familiar with is the <video> HTML tag. You only declare it using a one-line HTML tag as shown below;

<video src="./howtocreateapps.webm" controls></video>

Yet, what this one line does is remarkable. You get a play button, previous and next buttons, volume slider – all this stuff, appear without you having to write any HTML markups. Regardless of your CSS styling, the video player will appear the same. This is made possible by the Shadow DOM which holds the other markup including styles required to render the video in the browser.

Additional Resources for Learning Web Components

https://coryrylan.com/blog/introduction-to-web-components

https://designmodo.com/web-components/

https://css-tricks.com/an-introduction-to-web-components/

https://github.com/Polymer/polymer

https://itnext.io/web-components-using-polymer-cd7e2ea8d06e

https://dev.to/thepassle/web-components-from-zero-to-hero-4n4m#-a-components-lifecycle

Similar Posts