Understanding Web Components

Muhammad Isrin
10 min readMay 20, 2022

--

Maybe you are already familiar with the term “Component”, which is an important complement of an object. For example, a car has specific parts such as the front part used for the driver and the back part for passengers. Components can be interpreted in that way, just like in a website. In a website, you often see components like the footer, header, and sidebar. That’s what is meant by components in a website.

layout structure website
layout structure : https://www.ecurtisdesigns.com/wp-content/uploads/2014/02/layouts.jpg
website structure
website structure ( https://www.oxfordwebstudio.com/user/pages/06.da-li-znate/sta-je-struktura-sajta/sta-je-struktura-sajta.jpg )

As Frontend Engineers, we have certainly encountered problems in designing an application. One of those problems is constantly adding new lines of code for the exact same design. Imagine if there’s a section in our application that has a complex design, long class names, and requires unique attributes (e.g., id, class, etc.) in each part to handle different events in JavaScript. It is indeed a tiring task that consumes a lot of time, as we are essentially doing something repetitive over and over again.

So the proper solution to address this problem is by creating Web Components. Quoting from the official Mozilla developer page.

Web Components is a suite of different technologies allowing you to create reusable custom elements — with their functionality encapsulated away from the rest of your code — and utilize them in your web apps.

As a simple analogy, we can create a complex design that contains various types of content and wrap it within a single, simple HTML tag, just like building a building or any other object with Lego blocks. Web Components are like Lego pieces that you can design and fit together with other Lego pieces depending on the availability of slots. Sounds interesting, doesn’t it?

That sounds great! In this article, you’ll delve into a more fundamental and in-depth exploration of Web Components.

Web Component Specification

It should be understood that Web Components have several specifications as follows.

  1. Custom Elements is a set of JavaScript APIs that allows you to define custom elements and their behavior, which can then be used as desired in your user interface.
  2. Shadow DOM is a set of JavaScript APIs for attaching an encapsulated “shadow” DOM tree to an element, which is rendered separately from the main document DOM, and controlling related functionality. This way, you can hide the features of the element, allowing it to be written and styled without fear of conflicting with other parts of the document.
  3. HTML Templates are elements <template> and <slot> that allows you to write markup templates that are not displayed on the rendered page. These templates can then be reused multiple times as the basis for custom element structures.

For more details, you can visit Developer Mozilla Documentation

How to Implement Web Components?

Actually, there are several ways to implement web components. You can use pure HTML and JavaScript, use JavaScript frameworks with 2 modules or 2 apps, or use JavaScript frameworks with Polymer. However, in this article, you will focus more on the basic approach using pure HTML and JavaScript, with a brief example of using a JavaScript framework.

Basic example implementation Web Components

In this example, I will try to create a index.html file and a main.js file. In the index.html file, it contains the typical HTML structure and a simple HTML template, as well as a custom element derived from that template. The main.js file includes a script and a class to create or define a new element in HTML that can be used as a template.

index.html
main.js

From the above code example, in the index.html file, there is a <template> tag used as a template or component. There are also three custom components that utilize the previously created template, each with different slots or different content in each component.

The main.js file contains code that registers a new element, making it available for use on the HTML page. This allows the custom element to be recognized and rendered by the browser.

Result View

From the given sentence, it can be observed that there is a title written inside the <h1> tag in the body section. Below that, there are three paragraphs with a gray background, which is a pre-defined component. In the first paragraph, it represents the default content of the component when it doesn’t have any children or slots. Therefore, the default content from the template component will be displayed in that case.

In the second paragraph, there is different text displayed because a child or slot containing text has been passed into the component. This allows for dynamic content insertion, where the component can be customized by providing specific content through its children or slots.

In the third component, a slot list is passed into the previously created component. This means that the component has a designated area where multiple elements or content can be inserted dynamically. The slot list allows for flexibility in populating the component with various elements or content based on specific needs or requirements.

From the example above, we can see the flexibility and efficiency of a custom component. It is important to emphasize that in order to make the child/slot of the component flexible, the `slot` property is required on the HTML tag that will be used as a child, with the value of the slot property being the name of the `slot` tag in the template that has been created.

To explore more examples, you can visit the following GitHub repository: mdn web components example. The repository provides a collection of web component examples that demonstrate various use cases and features of web components. It can serve as a valuable resource to further understand and explore the capabilities of web components.

Example using Javascript Framework

In this example, we have two applications using different JavaScript frameworks, namely React JS and Svelte JS. React JS is used as the main app, while Svelte JS is used to create a reusable component that can be used in the React JS main app.

The flow of this example is as follows:
1. First, you create the component in the Svelte app and build the Svelte project.
2. The resulting bundled Svelte files can then be used directly as a component in the React JS main app.

Before proceeding with this example, make sure you are familiar with the installation of Svelte JS and React JS. You can refer to their respective documentation at the following links:
- Svelte JS: [https://svelte.dev/](https://svelte.dev/)
- React JS: [https://reactjs.org/docs/create-a-new-react-app.html](https://reactjs.org/docs/create-a-new-react-app.html)

If you are not familiar with the installation process, you can follow the provided guides in the documentation to install Svelte JS and create a new React JS app.

  • Installation svelte app

Running a command into a terminal like this

npx degit sveltejs/template my-web-component
cd my-svelte-project
npm install
npm run dev

Access `http://localhost:8080` and you will see the default Svelte app displayed in your browser as follows.

  • Setup your svelte code

In this step, we will modify several lines of code in the files of the Svelte app to transform it into a reusable component for the main app.

Open the previously created Svelte app, which is named my-web-component, using your favorite code editor. You will see the default folder structure as follows.

Next, open the main.js file and modify the code to remove unnecessary props and prevent creating or registering a new application in the DOM.

////// BEFORE : ///////////////
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
name: 'world'
}
});
export default app;

convert to :

////// AFTER : ///////////////
import App from "./App.svelte";
export default App;

After that, open the App.svelte file and adjust the code as follows.

<svelte:options tag="svelte-default-component" />
<script>
export let name = "World";
</script>

<main>
<h1>Hello {name}!</h1>
<p>
Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn
how to build Svelte apps.
</p>
</main>
<style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
}
@media (min-width: 640px) {
main {
max-width: none;
}
}
</style>

In the code above, it can be seen that the svelte tag is used to export the name of the tag that will be used as the component’s name.

<svelte:options tag="svelte-default-component" />
....

After that, build the Svelte app by running the following command: npm run build or yarn build. Wait until the process completes, and your web component will be ready to use in the main app.

  • Installation React App

Before installing the React app, create a new folder named “example-used” in the root folder of the Svelte application. This will result in the following folder structure.

Please run the following command in the root folder of the previously created Svelte app.

npx create-react-app example-used

After that, you will see the “example-used” folder created, and the folder structure will be as follows.

After that, navigate to the created React app folder, which is the “example-used” folder, and install the dependencies react-app-rewired by running the following command.

npm install react-app-rewired --save-dev or yarn add -D react-app-rewired

For more detailed information, you can refer to the documentation react-app-rewired at the following link: https://www.npmjs.com/package/react-app-rewired. The documentation provides comprehensive guidance on how to use `react-app-rewired` and its various features and configurations.

After completion, adjust the script section in the package.json file as follows.

....
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
},
....

Next, create a config-overrides.js file and insert the following code.

const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
module.exports = function override(config, env) {
config.resolve.plugins = config.resolve.plugins.filter(
(plugin) => !(plugin instanceof ModuleScopePlugin)
);
return config;
};

After that, open the App.js file in the /src folder and adjust the code as follows.

import logo from "./logo.svg";
import "./App.css";
// My web Components
import "../../../public/build/bundle";

function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
{/* Example Used Web Component */}
<h3>Custome Web Component</h3>
<svelte-default-component />
</header>
</div>
);
}
export default App;
  • Running your web component

After following the previous guide, you have created a Svelte application as a component and a React app as the main app.

To see the result of these applications, run the React app by executing the following command.

yarn start or npm run start

It will automatically open http://localhost:3000 in your browser, and you will see the result as follows.

That’s great to hear! It’s indeed a successful implementation of Web Components in multiple apps. Congratulations!

For further reference and development, you can explore the repository at https://github.com/MochIsrin068/svelteapp-web-component-starter. This repository can serve as a starting point for your future projects involving the Svelte app and Web Component integration.

Happy coding!

TL;DR

Indeed, Web Components are an excellent solution for developers, especially frontend developers, to tackle the complexity and repetition often associated with coding. They provide a way to encapsulate and reuse code, making it easier to maintain and develop applications.

Web Components can be a valuable reference for developing your own frameworks, as they offer a standardized approach to building reusable and encapsulated components. They align well with the current trends in frontend development and can be particularly useful in Microfrontend architectures, where individual components are developed independently and composed to form a larger application.

By leveraging Web Components, developers can create modular, reusable, and interoperable components that can be seamlessly integrated into various projects and frameworks. This promotes code reusability, enhances developer productivity, and fosters a more efficient and maintainable codebase.

Overall, Web Components offer a powerful and flexible solution for frontend development, enabling developers to build scalable and modular applications while reducing complexity and repetitive tasks.

References

--

--