An Introduction To Web Components
An Introduction To Web Components
https://academind.com/tutorials/web-components-introduction/ 1/26
8/24/2021 An Introduction to Web Components
Take a deep dive into building web components - with just JavaScript and a compiler,
named StencilJS.
Web Components are a set of web platform APIs that allow you to create
new custom, reusable, encapsulated HTML tags to use in web pages and
web apps.
For example, we can create our new component called <my-web-
component> , with its unique styling and functionality, and use it in any
JavaScript framework or library . And besides that, it works across most
modern browsers! Sounds too good to be true, doesn’t it?
https://academind.com/tutorials/web-components-introduction/ 2/26
8/24/2021 An Introduction to Web Components
The fact that these components are framework agnostic, makes creators
of component libraries more profitable and future proof as well. This is
why this is the next big thing and you should consider getting on board in
these early days and take advantage of it.
If you want to have some extra reading, visit the official website of Web
Components at webcomponents.org and the MDN Docs at
developer.mozilla.org/en-US/docs/Web/Web_Components .
# Building our first Web Component with Vanilla JavaScript
First of all lets see the end result on the screen of the Web Component
we’re gonna build, the one inside the red rectangle:
So, the app consists of an input field, where you can type your name, and
a greeting paragraph, outputting the name you entered, and below, a
Web Component that gives you the Google search result of the name. If
you click the link that says “here”, you can see the search result opened in
a new tab:
https://academind.com/tutorials/web-components-introduction/ 3/26
8/24/2021 An Introduction to Web Components
After creating this Web Component, we’re gonna build the same app in
React, Vue and Angular, and consume it in each app.
To create the Web Component, lets open a code editor and create a .js
file, that we can name search-result.js and paste this content there:
//search-result.js
template.innerHTML = `
<style>
div {
margin-top: 20px;
color: green;
}
</style>
<div>
`;
constructor() {
super();
https://academind.com/tutorials/web-components-introduction/ 4/26
8/24/2021 An Introduction to Web Components
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.shadowRoot.querySelector('a').href = '';
return ['name-attribute'];
if (name == 'name-attribute') {
this.shadowRoot.querySelector(
'a'
).href = `https://www.google.com/search?q=${newValue}`;
window.customElements.define('search-result', SearchResult);
You might be wondering what’s all the code above about, so lets see each
part step by step:
1. Create the template:
const template = document.createElement('template');
template.innerHTML = `
<style>
div {
margin-top: 20px;
color: green;
}
</style>
<div>
`;
Once we got our template ready, we need JavaScript to instantiate it, and
this can be done extending an interface called HTMLElement , creating
our custom HTML element.
If you are a bit lost here, but you have worked with React, remember when
you extended React.Component to create a class based component in
React. Here, we’re extending the HTMLElement interface instead, which is
native browser API, and not a class or interface from the React library.
4. Encapsulate the HTMLElement, append the template, and initialize
the href value of the <a> :
constructor() {
super();
this.shadowRoot.appendChild(template.content.cloneNode(true));
https://academind.com/tutorials/web-components-introduction/ 6/26
8/24/2021 An Introduction to Web Components
this.shadowRoot.querySelector('a').href = '';
The constructor of the parent interface needs to be called to inherit all the
methods and properties using the method super() . If you have used
React in the early days, super() was required when creating a class
based component. This constructor() runs right away when the
component is created at runtime.
To recap, we have already created the template and the HTML element.
Now, it’s time to use the shadow DOM to provide encapsulation — which
means being able to keep the markup structure, style, and behavior
hidden and separate from other code on the page so that different parts
do not clash, and the code can be kept nice and clean. The Shadow DOM
API is a key part of this, providing a way to attach a hidden separated
DOM to an element.
This step of using the shadow DOM is optional, but it’s the usual way of
writing clean components.
To attach the shadow DOM to an element, there’s a method called
attachShadow() which accepts an object with a key value pair mode:
'open' , to set the encapsulation mode for the shadow DOM tree. When is
open , the elements of the shadow root are accessible from JavaScript
outside the root, for example using Element.shadowRoot .
In other words, when writing in Vanilla JavaScript, we access the DOM
elements with the document object, like for example
document.querySelector('#title') ; to select an element with
id='title ; now, our Web Component will live inside the shadow DOM
(not at the main DOM tree root level) so we CAN’T use the document
object, but the shadowRoot object instead, which is the interface of the
Shadow DOM API and is the root node of a DOM subtree that is rendered
separately from a document’s main DOM tree.
So, now, we can access the web component at runtime with the
shadowRoot object and the Web Component’s content stored in the
https://academind.com/tutorials/web-components-introduction/ 7/26
8/24/2021 An Introduction to Web Components
template variable, and we can attach and remove event listeners, and
so on.
The line of code holding
this.shadowRoot.appendChild(template.content.cloneNode(tr
ue)); deep clones all the content of the template and appends it as a
child to our Web Component. More info about it here .
The href attribute can’t be hard-coded, because it depends on what the
user types inside the input field for the name. So, this content must be
added at runtime and, as a consequence, the <a> element must also be
accessed at runtime and have its href attribute value initialized with this
code: this.shadowRoot.querySelector('a').href = '';
5. Declare the watched attributes:
The app will pass the dynamic name via one attribute called name-
attribute , but Web Components don’t watch for attribute value
changes by default, so this must be done manually with a static method:
return ['name-attribute'];
In the returned array, all the names of the attributes we want to watch for
must be added.
6. React to changes in attribute values:
Inside our Web Component, there’s a method
attributeChangedCallback() available, that runs every time any of
the watched attributes change.
if (name == 'name-attribute'){
this.shadowRoot.querySelector('a').href = `https://www.google.com/se
}
https://academind.com/tutorials/web-components-introduction/ 8/26
8/24/2021 An Introduction to Web Components
window.customElements.define('search-result', SearchResult);
The first argument we pass to it is the name of the new custom element.
Note that custom element names must contain a hyphen (it can’t be
named searchresult ), and the second one is the constructor of the
new custom element.
That’s it! we have successfully created our first web component that
can be used in any JavaScript framework or library! wow!
Bonus:
There are other life-cycle methods available inside a Web Component,
and these are:
connectedCallback : Invoked when the custom element is first
connected to the document’s DOM.
https://academind.com/tutorials/web-components-introduction/ 9/26
8/24/2021 An Introduction to Web Components
React is the most popular Front End library used nowadays to build apps.
So, lets create a React project and consume our Web Component. The
final React app can be found in this gitHub repo . Lets follow these steps:
1. Create the App
Let’s call the app react-web-components . Feel free to choose other
name as well. In any folder, type these commands, one at a time:
cd react-web-components
npm start
https://academind.com/tutorials/web-components-introduction/ 10/26
8/24/2021 An Introduction to Web Components
import './App.css';
import './web-components/search-result';
function App() {
return (
<div className="App">
<input
https://academind.com/tutorials/web-components-introduction/ 11/26
8/24/2021 An Introduction to Web Components
value={name}
></input>
<search-result name-attribute={name}></search-result>
</div>
);
The code above stores the value from the <input> field in the state and
passes it to our Web Component <search-result> via the attribute
called name-attribute .
4. Modify /src/App.css , by adding this lines of code to give the app a
better look.
//App.css
.App {
text-align: center;
margin-top: 30px;
.greeting {
margin-top: 20px;
a) Let’s start by installing them. Open the terminal and run this command:
//package.json
"scripts": {
"postinstall": "vendor-copy"
},
//package.json
"vendorCopy": [
"from": "node_modules/@webcomponents/webcomponentsjs/custom-elements-e
"to": "public/vendor/custom-elements-es5-adapter.js"
},
"from": "node_modules/@webcomponents/webcomponentsjs/webcomponents-bun
"to": "public/vendor/webcomponents-bundle.js"
https://academind.com/tutorials/web-components-introduction/ 13/26
8/24/2021 An Introduction to Web Components
npm install
After this process finished, you’ll see a /public/vendor folder that has
been created. You’ll have two files inside it: custom-elements-es5-
adapter.js and webcomponents-bundle.js .
//index.js
<script src="%PUBLIC_URL%/vendor/webcomponents-bundle.js"></script>
<script src="%PUBLIC_URL%/vendor/custom-elements-es5-adapter.js"></script>
<!--! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->
6. Verify that you can run the application by running this in the
command line:
npm start
https://academind.com/tutorials/web-components-introduction/ 14/26
8/24/2021 An Introduction to Web Components
That’s it! Our React app uses our custom Web Component now! Well
done!
# Consuming the Web Component in Vue
npm i -g @vue/cli
If you get an error telling you that there aren’t permissions to access
certain folders, just add the word sudo before the command, and enter
your credentials.
2. Create a new Vue project:
Still in the terminal, run these commands (one at a time) to create a
project called vue-web-components ; feel free to choose other name as
well.
https://academind.com/tutorials/web-components-introduction/ 15/26
8/24/2021 An Introduction to Web Components
cd vue-web-components
https://academind.com/tutorials/web-components-introduction/ 16/26
8/24/2021 An Introduction to Web Components
<template>
<div class="App">
<search-result v-bind:name-attribute="name"></search-result>
</div>
</template>
<script>
import './web-components/search-result.js';
export default {
data() {
return {
name: '',
};
},
https://academind.com/tutorials/web-components-introduction/ 17/26
8/24/2021 An Introduction to Web Components
};
</script>
<style>
.App {
margin-top: 30px;
text-align: center;
.greeting {
margin-top: 20px;
</style>
https://academind.com/tutorials/web-components-introduction/ 18/26
8/24/2021 An Introduction to Web Components
//vue.config.js
module.exports = {
configureWebpack: {
plugins: [
new CopyWebpackPlugin({
patterns: [
context: 'node_modules/@webcomponents/webcomponentsjs',
from: '**/*.js',
to: 'webcomponents',
},
],
}),
],
},
};
The CopyWebpackPlugin will now copy over all the needed JavaScript
files into a webcomponents directory in the dist directory when
building the app.
https://academind.com/tutorials/web-components-introduction/ 19/26
8/24/2021 An Introduction to Web Components
c) Load polyfills:
Then, include the loader and an optional import for the ES5 compatibility
script in the <head> section of /public/index.html .
//index.html
<script src="webcomponents/webcomponents-loader.js"></script>
<script>
if (!window.customElements) {
document.write('<!--');
</script>
<script src="webcomponents/custom-elements-es5-adapter.js"></script>
<!-- ! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->
6. Verify that you can run the application by running this in the
command line:
npm run serve
That’s it! Our Vue App uses our custom Web Component now!
Congratulations!
https://academind.com/tutorials/web-components-introduction/ 20/26
8/24/2021 An Introduction to Web Components
npm i -g @angular/cli
If you get an error telling you that there aren’t permissions to access
certain folders, just add the word sudo before the command and enter
your credentials.
2. Create a new Angular project:
Still in the terminal, run this commands (one at a time) to create a project
called angular-web-components ; feel free to choose other name as
well.
ng new angular-web-components
cd angular-web-components
ng serve
https://academind.com/tutorials/web-components-introduction/ 21/26
8/24/2021 An Introduction to Web Components
https://academind.com/tutorials/web-components-introduction/ 22/26
8/24/2021 An Introduction to Web Components
To use two way data binding in our <input> element, lets add the
FormsModule to the imports array.
Angular will NOT recognize by default our custom HTML tag of our Web
Component, so lets add a schemas property inside the @NgModule
decorator, and add CUSTOM_ELEMENTS_SCHEMA inside the schemas
array. The code should look like this:
//app.module.ts
@NgModule({
declarations: [AppComponent],
providers: [],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
bootstrap: [AppComponent],
})
<div class="App">
<search-result [attr.name-attribute]="name"></search-result>
</div>
//app.component.css
.App {
text-align: center;
margin-top: 30px;
.greeting {
margin-top: 20px;
import './web-components/search-result.js';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
name;
https://academind.com/tutorials/web-components-introduction/ 24/26
8/24/2021 An Introduction to Web Components
b) You need to copy over the polyfills to load them. You can do this by
adding them to the assets array in angular.json located at the root
level of your project. Now, your assets array should look like this:
//angular.json
"assets": [
"src/favicon.ico",
"src/assets",
"glob": "**/*.js",
"input": "node_modules/@webcomponents/webcomponentsjs",
"output": "webcomponents/"
c) Then, include the loader and an optional import for the ES5
compatibility script in the <head> section of /src/index.html .
//index.html
<script src="webcomponents/webcomponents-loader.js"></script>
<script>
if (!window.customElements) {
document.write('<!--');
</script>
<script src="webcomponents/custom-elements-es5-adapter.js"></script>
<!-- ! DO NOT REMOVE THIS COMMENT, WE NEED ITS CLOSING MARKER -->
9. Verify that you can run the application running this command on the
terminal:
ng serve
https://academind.com/tutorials/web-components-introduction/ 25/26
8/24/2021 An Introduction to Web Components
That’s it! Our Angular App uses our custom Web Component now!
Excellent!
This was just an introductory article about Web Components, so I
encourage you to keep exploring and experimenting. Have fun and happy
coding!
Web Components & Stencil.js
Take a deep dive into building web components - with just JavaScript and a compiler,
named StencilJS.
https://academind.com/tutorials/web-components-introduction/ 26/26