Top 10 Mistakes in Web Components

Top 10 Mistakes in Web Components

Web Components enable custom element creation and sharing on a whole new level that has not really been seen to date but is so desperately needed. Developers of everything from simple webpages to complex applications are using Web Components to deliver new functionality, new behaviors, new designs.

Web Components are a big part of the future of the web.

There are lots of articles detailing how to build a basic Web Component, but almost no article details how to solve some of the gotchas once you start down that road. That's what this article serves to do; point out some of the things every Web Component developer is overlooking and to which they should probably be giving more consideration.

1). Not Using a Web Component Framework

The APIs which make up the Web Components standards (Custom Elements, ShadowDOM, etc) are intentionally low level APIs. As such they are not always the most clear or concise in their understandability. Additionally, because they are intentionally low level, there is a lot of little details that they do not directly address but are necessary to properly deliver the promise of a Web Component.

Save the trouble and just use one of the existing Web Component frameworks.

A Web Component framework wraps and works on top of the Web Component standards to make writing components easier and faster and more concise. A good framework abstracts the APIs away and just lets you focus on writing the component itself, instead of having to worry about the nitty gritty details.

The ZephJS framework, for example, enables writing components in a very simple declarative syntax without requiring you to understand all the details behind Web Components. ZephJS is perfect for anyone getting started with Web Components because it requires almost no knowledge of the Web Component APIs. Other frameworks such as lit-element or Hybrids are also worth consideration.

Here's a simple example from ZephJS that defines a <my-button> component...

import {ZephComponents} from "./Zeph.js";
import {html,css,attribute,property,bind,onCreate,onEvent} from "./zeph.min.js";

ZephComponents.define("my-button",()=>{
html("./my-button.html");
css("./my-button.css");

attribute("icon","");
attribute("icon-placement","left");
attribute("disabled",undefined);

property("clickCount",0);

bind("@icon","button &gt; img","@src");
bind("@disabled","button");

onCreate((element)=&gt;{
	console.log("Element '"+element.getAttribute("name")+"' created!",element);
});

onEvent("click",(event,element)=&gt;{
	element.clickCount += 1;

	console.log("Button '"+element.getAttribute("name")+"' clicked "+element.clickCount+" times.");
});

});

Because of the readability of ZephJS, this article will use it for all of its examples going forward.

2). Over-Styling

One of the goals of writing a Web Component is to allow others to use it. The promise of sharing and reusability are one of the things that make Web Components so attractive. Yet, in order to share components there are a lot of considerations one must take into account, the least of which is how the component is going to be styled by others.

One of the primary goals of a Web Component is something called Encapsulation. This means that the content and styles of a Web Component are encapsulated (limited to) just that component. Content is hidden (somewhat) from the primary DOM tree. Likewise, styles within a Web Component do not leak out and effect anything else. This is a really useful concept and one of the most powerful features of Web Components. However, encapsulation comes at a price; content and style does not leak out, but it also does not leak in either. There is no direct way (currently) to actively target the content or styling of a Web Component itself. It is intentionally (mostly) isolated.

For Web Component users though, this can be a very limiting factor if the component is not designed well. Imagine we have a button component called <my-button> and inside the components style we set the background-color to red. But along comes a user that wants to set the background-color to green. With Web Components today, that is just not possible thing to do. There is no way to actively target the background color of what is in a Web Component.

However, what does work is using the cascading nature of CSS to style into the Web Components. By writing Web Components that do not overload things like colors or fonts, one are allows component users to let the cascade of their styles apply. For example, if one sets font-family in the body of the document, any Web Component used will have the same font-family unless it is changed within the web component itself.

In the future some of this will change. In particular the ::part and ::theme proposal currently undergoing review will allow Component authors to expose parts of their components to styling. This will allow for more flexibility in Web Components, but that is still a long ways away.

3). Fixed Measurements

Imagine oneself as a component user of the <my-button> component. We have downloaded the component from the web, dropped it into the directory structure, and included it in the code. We insert the <my-button> tag in the page right where we want a great big "CLICK HERE" button to show up. We press refersh and are incredibly disappointed to find a tiny little button that says "CLICK HERE". We have just run afoul of another type of overstyling, the fixed dimensions dilemma. Somewhere in the code of the <my-button> component that author has fixed the width of a button at 150px.

As a component author one should not be constraining how a compenent user will use the component. Yet time and again one sees components that define a fixed width or height. By doing so, the component author is not leaving space for the component to be scaled or driven by the external (to the component) spacing needs.

Now, there are a few cases where, yes, a fixed width or height is a useful thing. But by and large, Web Component authors need to free their components to shrink or grow based on the containing layout and space. This is even more important as display layouts like grid and flexbox are used more and more. These layouts are specifically geared toward flexible width and height components. scalable Web Component that support dimensional growth are ones that get resused the most, over and over again.


4). Forgetting About Focus

A very common oversight when writing a Web Component is to not understand or give any thought to how the component will work with regards to Focus. Focus is the process of a browser targeting a specific Element to receive user input events like keystrokes or mouse clicks. At any given time, a browser may only have one element that is the current focus. When a key is pressed the focused element is the one that receives the associated key event first.

The rules for what gets the focus and how focus changes in a browser is complicated and can be very confusing. To compound this fact, the browser has very little support for making this understanding easier. However, there is a proposal, the Focus Traversal API, for making this better.

Furthermore, there is not a lot of real information about how focus works with regards to Web Components, so allow us to clarify: Focus will descend into the Web Component's shadowDOM if there is a focusable element within it AND the component does not have a tabindex attribute of -1. Additionally, when a focus or blur event occurs inside a Web Component, the event target will be rewritten (in a process called "retargetting") to appear as if the event occured on the Web Component itself instead of on the element within the Web Components ShadowDOM.

The target rewriting can especially trip up a lot of custom focus traversal systems and should be protected against. A good rule of thumb when writing a Web Component is to specifically set the tabindex of any component. If the component has something that needs to receive focus, set the tabindex to "0" to ensure that it can and then forward focus to the internal content element that would need it. (If multiple elements need focus, forward to the first.) If the component does not want the focus specifically, set tabindex to "-1" to ensure that it does not get the focus ever.

Here's an example written in ZephJS:

ZephComponents.define("my-widget",()=>{
html( &lt;input type="text"&gt;&lt;/input&gt; );

// sets tabindex attribute for this component
attribute("tabindex","0");

// forward focus from the component to the internal contents
// input element.
onEvent("focus",(event,element,content)=&gt;{
	let next = content.querySelector("input");
	next.focus();
});

});


5). Forgetting About Localization

The difference between any old Web Component and a professional Web Component often lies in localization. Localization is the ability of a component (or any software for that matter) to be delivered to users of different languages. A Web Component that has some text within it is only localizable if that text can be changed.

For example, say one has a Yes/No component where users can choose between the Yes state and the No state. Here's a simple example in ZephJS:

ZephComponents.define("my-yesno-chooser",()=>{
html( &lt;div class="question"&gt;&lt;/div&gt; &lt;div class="chooser"&gt; &lt;span class="yes"&gt;Yes&lt;/span&gt; or &lt;span class="no"&gt;No&lt;/span&gt; &lt;/div&gt; );

attribute("question","");
attribute("value","");

bind("@question",".question","$");

onEventAt(".yes","click",(event,selected,element,content)=&gt;{
	element.setAttribute("value","yes");
});
onEventAt(".no","click",(event,selected,element,content)=&gt;{
	element.setAttribute("value","no");
});

});

In this example, both the "Yes" and the "No" text is not localizable because there is no way for the component user to change it. Also, the separator text of "or" is not localizable. That means if a component user wanted to change "Yes" to "Oui" for his French users they could not without some fancy javascript.

A better solution would be to allow a component attribute to drive what the Yes (or No) text is. Like this:

ZephComponents.define("my-yesno-chooser",()=>{
html( &lt;div class="question"&gt;&lt;/div&gt; &lt;div class="chooser"&gt; &lt;span class="yes"&gt;&lt;/span&gt;&lt;span class="separator"&gt;&lt;/span&gt;&lt;span class="no"&gt;&lt;/span&gt; &lt;/div&gt; );

attribute("question","");
attribute("yesText","Yes");
attribute("noText","No");
attribute("separator"," or ");
attribute("value","");

bind("@question",".question","$");
bind("@yesText",".yes","$");
bind("@noText",".no","$");
bind("@separator",".separator","$");

onEventAt(".yes","click",(event,selected,element,content)=&gt;{
	element.setAttribute("value","yes");
});
onEventAt(".no","click",(event,selected,element,content)=&gt;{
	element.setAttribute("value","no");
});

});

Notice in this example that one can use that "yesText", "noText", and "separator" attributes to set the text of the component. If these attributes are ommitted, the component falls back to the default english. (One might consider making the default a "1" or "0" to make the component even more localization friendly.)

6). Forgetting About Accessibility

Accessibility centers around the ability of users with disabilities to interact with a Web Component. And modern web browser standards have made incredible strides at giving web developers tools to easily add accessibility into their pages. The ARIA work in particular is very useful and compelling.

Yet for some reason, like localization, most Web Component authors spend zero effort on accessibility and this is extremely problematic. If a component does not have the necessary accessibility information and affordances it is ignoring an entire class of users (and even potentially opening themselves up to legal liabilty). And because ARIA is chiefly achieved through element markup and Web Components are not addressable externally, users of a Web Component cannot add accessibility after the fact.

Good Web Component design takes accessibility into account from the start. ARIA attributes are librally used and applied. Keyboard navigation is provided instead of relying solely on mouse navigation. Components are tested against screen readers to ensure that they flow correctly. Indicators are provided not just by color but by other means as well. Also, keep in mind the localization points from above; when using ARIA attributes make sure that they can be localized as well.

To give you an example of how bad developers are at accessibility it should be pointed out that not once in any of the examples were there any accessibility examples. We, as a comunity of developers, must strive to do better.

7). Not Using Slots

One of the underlying Standards for Web Components is HTML Templates API. Templates enable a key parts of Web Components: slots. Slots allow a Web Componnet to identify a space for the innerHTML of the component to be projected into.

Say we have a Web Component called <my-button>. And using it we write the following HTML:

ZephComponents.define("my-button",()=>{
html( &lt;button&gt;&lt;/button&gt; );
});
<my-button>
<img src="./my-button-icon.jpg" />
<span>Click Here!</span>
</my-button>

The innerHTML of the <my-button>, the <img> and the <span>, will be lost unless the Web Component specifically offers a <slot> to project into the Web Component. Instead the Web Component should look like this:

ZephComponents.define("my-button",()=>{
html( &lt;button&gt; &lt;slot&gt;&lt;/slot&gt; &lt;/button&gt; );
});

The <slot> element identifies where the innerHTML content is projected. One could bury the <slot> element in fifteen nested <div> tags and that is where the content would be projected. There's a little more to <slot> such as named slots which allow one to project specific parts to specific slots, but that is a topic for some self reading.

8). Over Engineering

It is easy to envision building a Web Component that does all the amazing things you want it to do. Resist this urge. The more complexity one builds into a component, the more likely it is to be unusable by others.

Instead, consider building simple components and building them well. Makw sure they are localized and accessible, make sure they are flexible and styles cascade into them. Keep them simple.

If the end goal needs a more complicated solution, consider building a set of lower level components and then wrapping them up into the higher component. For example, if one is building a Tab container, build out several components like a Tab Heading, a Tab Body, a Tab Header, and a Tab Page, and bind them altogether into a single Tab component.

Simple components are more testable, more accessible, and better for the end users.

9). Zip Files

Since a primary reason to build a Web Component is to share it with the world, one needs a means to do so. The most common approach for doing this is to put all the files into a Zip File and then tell users how and where to extract it. This usually involves complicated instruction on where the files need to be placed, a bunch of <script> and <link> style loading tags to be inserted, and a whole lot of trail and error by the user to get it all working.

This is messy and cumbersome for Web Developers and often costs them the one resource they dont have enough of: time. Instead, consider some of the techniques one can use in a component (or component library) to get everything down to just one file:

  • Inline HTML in the Web Component: This is usually the default case, but in some systems the HTML content can be separated out. This is preferred because it is cleaner, but it also makes it harder on users.
  • Inline CSS or just Style In JavaScript: The same goes for CSS. Inline is better for the end users, but harder for the developers. Another common recommendation here is to have an external style sheet and then use an @import inside of the Web Component to do the styling. Do not do this (yet). as it can cause performance and memory degredations in a site. There is a proposal for this in the W3C that is working its way forward, but its still a long way off.
  • Inline Assets: Putting assets (images, audio files, videos, etc) directly into a Web Component JS can be done using data: urls, or for images one could use SVGs instead of image files. Either will allow one to put the asset data directly into the component definition thus keeping everything all together.

The ultimate goal is to ship just one file that contains everything for a component or component library. This means there is one import that needs to be done and no complicate directory layouts that need to be managed. It's just plain simple.

Of note, ZephJS, has a nice bundle utility that is built on rollup and acorn that does all of this. So one can keep the HTML, CSS, and assets all as separate files and then using the ZephJS bundle utility bundle it all up into a single JS file for distribution. Worth considering.

10). Not Publically Releasing

Finally, the last mistake most Web Component authors are making is just not releasing their work. One of the entire points of Web Components is reuse. Reuse in web pages and apps and also reuse by others. And this only happens by putting them out there. Please, publish components to npm and get the word out. Share them on webcomponents.org.

Of course this article would be remiss if it did not reiterate everything it just said. So share, but make sure the components are ready to be shared. Make sure they are well design, simple, not overly styled, flexible, localizable, accessable, and small. And then share them with the world.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow us on Facebook | Twitter

Learn More

The Web Developer Bootcamp

Angular 7 (formerly Angular 2) - The Complete Guide

The Complete JavaScript Course 2019: Build Real Projects!

Modern React with Redux [2019 Update]

Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

Build Responsive Real World Websites with HTML5 and CSS3

An Introduction to Web Components

Introduction to Ionic 4: How Web Components Changed the Game

PWA starter kit: build fast, scalable, modern apps with Web Components

An Introduction to Web Workers

Introduction to Service Worker - Progressive Web App Training

How to build a Progressive Web Apps

WebAssembly for Web Developers

Web Components Tutorial: Go from zero to hero

Mobile App Development Company India | Ecommerce Web Development Company India

Mobile App Development Company India | Ecommerce Web Development Company India

Best Mobile App Development Company India, WebClues Global is one of the leading web and mobile app development company. Our team offers complete IT solutions including Cross-Platform App Development, CMS & E-Commerce, and UI/UX Design.

We are custom eCommerce Development Company working with all types of industry verticals and providing them end-to-end solutions for their eCommerce store development.

Know more about Top E-Commerce Web Development Company

React Web Development: A Guide to Develop Progressive Web Applications

React Web Development: A Guide to Develop Progressive Web Applications

Outperform your competition with progressive web development and React.

Progressive web applications (PWAs) quickly gained popularity because they are web performance applications based on fast performance, streamlined to provide a mobile app-like experience. PWAs are built using HTML, CSS, and JavaScript to create a level of availability and performance equivalent to that of native mobile applications. They respond quickly, consume less data, store more space, and support push notifications and offline use in the browser.

Building a progressive web application has now become the web development trend that every business wants to follow. Significant players like Twitter and Flipboard have recently rolled out their progressive web apps to provide a mobile experience for users, without requiring them to install the app. In this article, you will learn how to build a progressive web application using React. Let's get started.

Step One — Set up the React Application

First, create a React application with create-react-app. To do so, you need to run the following commands:

  • npm install -g create-react-app
  • create-react-app pwa-app

Now, install React Router:

You need to replace the content of src / App.js using the code below to get a basic template with navigation.

import React, { Component } from 'react';
import { Router, browserHistory, Route, Link } from 'react-router';
import './App.css';

const NavBar = () => (
<div className="navbar">
<Link to="/">Feed</Link>
<Link to="/profile">Profile</Link>
</div>
);

const Template = ({ title }) => (
<div>
<NavBar />
<p className="page-info">
This is the {title} page.
</p>
</div>
);

const Feed = (props) => (
<Template title="Feed"/>
);

const Profile = (props) => (
<Template title="Profile"/>
);

class App extends Component {
render() {
return (
<Router history={browserHistory}>
<Route path="/" component={Feed}/>
<Route path="/profile" component={Profile}/>
</Router>
);
}
}
export default App;

Now, you'll have to update the default styles by replacing your src/App.css with the styles below to make your application look clean.

.navbar {
background-color: #01C8E5;
text-align: center;
}

.navbar a {
display: inline-block;
padding: 10px;
color: #fff;
text-decoration: none;
}

.page-info {
text-align: center;
font-weight: bold;
}

Then, run npm start to test the application in the browser. It is basically an application with two routes. Now, you will convert it to PWA.

Step Two — Lighthouse Setting and Auditing

Lighthouse is an automated open-source tool for testing applications against PWA checklists. It facilitates audits for accessibility, performance, and more.

Check your application with Lighthouse. Click the Lighthouse icon from the top right corner in Chrome and then click the "Create Report" button. The generated report will look like this:

Creating a report to test your PWA with Lighthouse

Fix all failed audits.

Step 3 — Sign Up for a Service Staff

Service employees are proxy servers that connect the application and the network. With Service Worker, you will have to block network requests and save cached files. It allows your application to work even with an unavailable system.

Create an empty worker.js file in your application's general directory and add the following code to that file.

// Flag for enabling cache in production
var doCache = false;

var CACHE_NAME = 'pwa-app-cache';

// Delete old caches
self.addEventListener('activate', event => {
const currentCachelist = [CACHE_NAME];
event.waitUntil(
caches.keys()
.then(keyList =>
Promise.all(keyList.map(key => {
if (!currentCachelist.includes(key)) {
return caches.delete(key);
}
}))
)
);
});

// This triggers when user starts the app
self.addEventListener('install', function(event) {
if (doCache) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
fetch('asset-manifest.json')
.then(response => {
response.json();
})
.then(assets => {
// We will cache initial page and the main.js
// We could also cache assets like CSS and images
const urlsToCache = [
'/',
assets['main.js']
];
cache.addAll(urlsToCache);
})
})
);
}
});

// Here we intercept request and serve up the matching files
self.addEventListener('fetch', function(event) {
if (doCache) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
}
});

Now, check if the browsers support service staff and then register worker.js. To do this, you need to add the following script to the file public/index.html (note that shrink-to-fit=no in the viewport meta tag has been deleted).

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('worker.js').then(function(registration) {
console.log('Worker registration successful', registration.scope);
}, function(err) {
console.log('Worker registration failed', err);
}).catch(function(err) {
console.log(err);
});
});
} else {
console.log('Service Worker is not supported by browser.');
}
</script>
</body>
</html>

You must restart your application and reload the browser after which you will see the Successful registration of member workers on the developer console. Now, recreate the Lighthouse report.

Step 4 - Improve the Progressive Nature of the Application

Your application will display an original blank div until the JavaScript loads and React hooks the original route. You must make sure your application works without downloading JS and displaying a bit of CSS and HTML before React takes effect. Your updated Index.html will look like this:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<title>React App</title>
<style type="text/css">
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.navbar {
background-color: #01C8E5;
text-align: center;
}
.navbar a {
display: inline-block;
padding: 10px;
color: #fff;
text-decoration: none;
}
.page-info {
text-align: center;
font-weight: bold;
}
</style>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root">
<div class="navbar">
<a href="/">Feed</a>
</div>
<p class="page-info">
Loading an awesome app...
</p>
</div>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('worker.js').then(function(registration) {
console.log('Worker registration successful', registration.scope);
}, function(err) {
console.log('Worker registration failed', err);
}).catch(function(err) {
console.log(err);
});
});
} else {
console.log('Service Worker is not supported by browser.');
}
</script>
</body>
</html>

Now, use Lighthouse to retest your application, and you'll see an improvement in the performance of the application.

Step 5 - Add the Splash Icon

You are required to add a 512x512 icon to display on the screen. To do so, you will have to update the manifest.json file and add the t0 icon to the public directory.

{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "/",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}

Also, use the following meta tags to allow the browser to determine that your application is a PWA.

<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes">
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">
Step 6 — Implement PWA

Now, only HTTPS is missing, and the cache can be fixed after you deploy the application. Update the doCache flag with true in the worker.js file. Create a new project in the firebase dashboard and name it "Pwa Application." Then, run the following command in the project directory:

npm install -g firebase-tools
firebase login
firebase init

Your Firebase.json will look like this:

{
"hosting": {
"public": "build",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}

After initializing, building and deploying your application.

  • npm run build
  • firebase deploy

You will see results after you test the application using Lighthouse on the deployed URL.

Final product with Lighthouse

Finally, you have created your first progressive web application with React.js!

Originally published by Manoj Kumar Bardhan at  dzone.com

=======================================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Understanding TypeScript

☞ Typescript Masterclass & FREE E-Book

☞ React - The Complete Guide (incl Hooks, React Router, Redux)

☞ Modern React with Redux [2019 Update]

☞ The Complete React Developer Course (w/ Hooks and Redux)

☞ React JS Web Development - The Essentials Bootcamp

☞ React JS, Angular & Vue JS - Quickstart & Comparison

☞ The Complete React Js & Redux Course - Build Modern Web Apps

☞ React JS and Redux Bootcamp - Master React Web Development


Web Development Services

Web Development Services

As one of the best Web Application Development Company, it provides a fine quality mobile app development service at an affordable price. Especially, it encourage start-ups that have unique ideas, by offering a more competitive price

HireFullStackDeveloperIndia is rated as one of the top Web Application Development Company in India by various industry magazines and review sites. They have a right blend of award-winning designers, expert programmers and Google certified digital marketers which make them a unique one-stop solution for hundreds of our clients, spread across all countries.

A Good website reflects not only your business but also it is one of the main factors why a potential customer would convert into Client. A good website design helps increase traffic driving leads to grow business. The best web design company create a custom design for each corporate website so as to help them meet their business goals.

Get Quote: https://hirefullstackdeveloperindia.com/get-a-quote/