Web Components
It's all rainbows and unicorns! Is it?
Sara HARKOUSSE
DevFest Nantes
19, 20 Octobre 2017
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
https://www.youtube.com/watch?v=ic4e50BK_ik
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
#devfestnantes #webcomponents @Sara_harkousse
Available recording in English
SARA HARKOUSSE
@Sara_harkousse
Tech Lead, front-end Web developer at Dassault Systèmes
3D design & PLM software
Electronics and Computer Science Engineer by training
About me
#devfestnantes #webcomponents
Women in Tech
Duchess France
@duchessfr
duchess-france.org
Elles bougent (Girls on The Move)
@ellesbougent
ellesbougent.com
#devfestnantes #webcomponents @Sara_harkousse
Web Components
It's all rainbows and unicorns! Is it?
http://vignette2.wikia.nocookie.net/weirdcommunity/images/a/a2/Rainbow-flow-abstract-backgrounds-for-powerpoint.jpg/revision/latest?cb=20130603085532
-
"The web components revolution"
-
"A Tectonic shift for web development"
-
"Web components are a game changer"
Web components'
public image
#devfestnantes #webcomponents @Sara_harkousse
Web components'
public image
#devfestnantes #webcomponents @Sara_harkousse
-
"The broken promise of Web Components"
Outline of this talk
#devfestnantes #webcomponents @Sara_harkousse
-
Motivation
-
Refresher on web components
-
Dive deep
-
Concluding remarks
Motivation
#devfestnantes #webcomponents @Sara_harkousse
-
Modular architecture
Filterable Product Table
Search Bar
Product Table
Product Row
Product Category Row
https://facebook.github.io/react/docs/thinking-in-react.html
#devfestnantes #webcomponents @Sara_harkousse
Angular 4.0 Component
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>`
})
export class AppComponent { name = 'Angular'; }
<my-app><h1>Hello Angular</h1></my-app>
https://angular.io/tutorial/toh-pt1#show-the-hero
#devfestnantes #webcomponents @Sara_harkousse
Ember 2.16.0 Component
<article class="blog-post">
<h1>{{title}}</h1>
<p>{{yield}}</p>
<p>Edit title: {{input type="text" value=title}}</p>
</article>
{{#each model as |post|}}
{{#blog-post title=post.title}}
{{post.body}}
{{/blog-post}}
{{/each}}
https://guides.emberjs.com/v2.16.0/components/defining-a-component/
#devfestnantes #webcomponents @Sara_harkousse
Polymer 2.0 Element
// Define the class for a new element called custom-element
class CustomElement extends Polymer.Element {
static get is() { return "custom-element"; }
constructor() {
super();
this.textContent = "I'm a custom-element.";
}
}
// Register the new element with the browser
customElements.define(CustomElement.is, CustomElement);
<custom-element></custom-element>
http://plnkr.co/edit/PaCt2M?p=preview
#devfestnantes #webcomponents @Sara_harkousse
Frameworks make it hard to get along
#devfestnantes #webcomponents @Sara_harkousse
Harmony happens when there is less learning curve
Browser support
https://www.webcomponents.org/
-
use webcomponents.js
#devfestnantes #webcomponents @Sara_harkousse
Refresher on web components
Web components are a set of web platform APIs that allow you to create new custom, reusable, encapsulated HTML tags to use in web apps.”
https://www.webcomponents.org/
#devfestnantes #webcomponents @Sara_harkousse
Refresher on web components
#devfestnantes #webcomponents @Sara_harkousse
-
HTML Template Tag
-
Shadow DOM
-
Custom Elements
-
HTML Imports
HTML Template Tag
#devfestnantes #webcomponents @Sara_harkousse
<template id="template">
<div id="container">
<img class="webcomponents" src="logo.svg">
</div>
</template>
https://github.com/SaraHarkousse/Web_Components/tree/master/VanillaJS/Template
HTML Template Tag Usage
#devfestnantes #webcomponents @Sara_harkousse
var template = document.querySelector('#template');
var clone = template.content.cloneNode(true);
var host = document.querySelector('#host');
host.appendChild(clone);
https://github.com/SaraHarkousse/Web_Components/tree/master/VanillaJS/Template
HTML Template Tag
#devfestnantes #webcomponents @Sara_harkousse
-
A way to add inert DOM elements to your document
-
Not something that's going to revolutionize your apps
-
No two-way data binding, no binding at all
#devfestnantes #webcomponents @Sara_harkousse
Shadow DOM
-
A tiny document
-
exists inside of a host element
#devfestnantes #webcomponents @Sara_harkousse
Key concepts
-
Isolated DOM
-
Scoped CSS
#devfestnantes #webcomponents @Sara_harkousse
Shadow DOM requires a polyfill
-
Hard to polyfill
#devfestnantes #webcomponents @Sara_harkousse
Use/Don't use
Shadow DOM?
callback() {
// Use it
this.root = this.attachShadow({mode: 'open'});
var template = document.querySelector('#template');
var clone = document.importNode(template.content, true);
this.root.appendChild(clone);
}
callback() {
// Don't Use it
this.root = this;
var template = document.querySelector('#template');
var clone = document.importNode(template.content, true);
this.root.appendChild(clone);
}
#devfestnantes #webcomponents @Sara_harkousse
Use/Don't use
Shadow DOM?
/* Use it */
:host {
color: red;
}
/* Don't use it */
custom-component {
color: red;
}
#devfestnantes #webcomponents @Sara_harkousse
Use AND Don't use
Shadow DOM
if (shadowflag){
this.root = this.attachShadow({mode: 'open'});
} else {
this.root = this;
}
custom-component, :host {
color: red;
}
#devfestnantes #webcomponents @Sara_harkousse
Custom Elements
class CustomButton extends HTMLElement {...}
window.customElements.define('custom-button', CustomButton);
<custom-button></custom-button>
-
Acts like a div
#devfestnantes #webcomponents @Sara_harkousse
Custom Elements
class CustomButton extends HTMLButtonElement {...}
window.customElements.define('custom-button', CustomButton, {extends: 'button'});
<button is="custom-button" disabled>My button!</button>
-
Acts like a real button
#devfestnantes #webcomponents @Sara_harkousse
Custom Elements Namespace
-
Dash (-) rule
#devfestnantes #webcomponents @Sara_harkousse
Custom Elements ES6 Class
class Custom-component extends HTMLElement {
constructor() {
super(); // always call super() first in the ctor.
...
}
connectedCallback() {
...
}
disconnectedCallback() {
...
}
attributeChangedCallback(attrName, oldVal, newVal) {
...
}
}
HTML Imports
#devfestnantes #webcomponents @Sara_harkousse
<link rel="import" href="component.html">
<link rel="stylesheet" href="style.css">
<div id="container">
<img class="rotate" src="logo.svg">
</div>
<script src="script.js"></script>
[Deprecation] Styling master document from stylesheets defined in HTML Imports is deprecated, and is planned to be removed in M65, around March 2018. Please refer to https://goo.gl/EGXzpw for possible migration paths.
How to get my component?
#devfestnantes #webcomponents @Sara_harkousse
var link = document.querySelector('link[rel="import"]');
var content = link.import;
// Grab DOM from component.html's document.
var el = content.querySelector('#container');
var clone = el.cloneNode(true);
var host = document.querySelector('#host');
host.appendChild(clone);
#devfestnantes #webcomponents @Sara_harkousse
Hammering our server
-
Each one of the HTML imports is another XMLHttpRequest
#devfestnantes #webcomponents @Sara_harkousse
Build tools for HTML Import
-
e.g. Vulcanize (turns all imports into one import)
#devfestnantes #webcomponents @Sara_harkousse
HTML Import requires a polyfill
-
ES module?
https://www.webcomponents.org/
#devfestnantes #webcomponents @Sara_harkousse
ES module
// export feature
export const Component = // …
// import feature
import {Component} from '../components/cutom-component.js';
#devfestnantes #webcomponents @Sara_harkousse
Component example
Bootstrap Progress Bar
<div class="progress">
<div class="progress-bar" style="width: 60%;">
60%
</div>
</div>
#devfestnantes #webcomponents @Sara_harkousse
Component example
class ProgressBar extends HTMLElement {
constructor() {
super(); // always call super() first in the ctor.
this.shadow = this.attachShadow({mode: 'open'});
this._complete = 0;
}
get complete() {
return this._complete;
}
set complete(val) {
this.setAttribute('complete', val);
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
static get observedAttributes() {
return ['complete'];
}
attributeChangedCallback(name, oldval, newval) {
// code
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
Component example
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
attributeChangedCallback(name, oldval, newval) {
var innerBar = this.shadow.querySelector('.progress-bar-inner');
switch(name) {
case 'complete':
this._complete = parseInt(newval, 10) || 0;
innerBar.style.width = this.complete + '%';
innerBar.innerHTML = this.complete + '%';
}
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
Component example
#devfestnantes #webcomponents @Sara_harkousse
class ProgressBar extends HTMLElement {
connectedCallback() {
var template = `<style>
.progress-bar {
width: 50%;
...
}
.progress-bar-inner {
height: 100%;
....
}
</style>
<div class="progress-bar">
<div class="progress-bar-inner">${this.complete}%</div>
</div>`;
this.shadow.innerHTML = template;
}
}
https://jsfiddle.net/sara_harkousse/kwwe75yy/
Component example
#devfestnantes #webcomponents @Sara_harkousse
window.customElements.define('progress-bar', ProgressBar);
// Use
<progress-bar></progress-bar>
Component example
#devfestnantes #webcomponents @Sara_harkousse
Components on a page
<!doctype html>
<html lang="en">
<head>
<link rel="import" href="/components/CustomNavbar.html">
..
</head>
<body>
<custom-navbar style="compact"></custom-navbar>
<custom-toolbar style="full"></custom-toolbar>
<custom-pagecontent>
<custom-input attr="val"></custom-input>
<progress-bar></progress-bar>
</custom-pagecontent>
<script>
document.querySelector('custom-input').dispatchEvent(new CustomEvent('customevent', {
detail: { prop: true }
}));
customElements.whenDefined('progress-bar').then(() => {
document.querySelector('progress-bar').addEventListener(
'customevent', function () {
// do something
}
});
});
</script>
</body>
</html>
#devfestnantes #webcomponents @Sara_harkousse
Takeaway
-
Template tag? yeah! why not?
-
Use ES module instead of HTML Imports
-
Use Shadom DOM with a flag
-
Custom Elements?? Go, Go, Go
#devfestnantes #webcomponents @Sara_harkousse
Takeaway
You will understand some of the design decisions of major frameworks if you learn about custom elements
#devfestnantes #webcomponents
Thanks for listening!
Follow for slides
@Sara_harkousse
https://github.com/SaraHarkousse
Web Components: It’s all rainbows and unicorns! Is it?
By sara_harkousse
Web Components: It’s all rainbows and unicorns! Is it?
Web components are a tale of four w3c specifications. They are a hot topic now. We’ve all seen big headlines, for instance, “The Web Components revolution”, “Web Components are a game changer”, “A Tectonic Shift for Web Development”, … and so many others. They are certainly exciting and promising, nevertheless, there are some factors holding them back such as performance issues and lack of browser support. Some features seem to be more hassle than they’re worth. In this talk you’ll examine web components from a pragmatic stand point. So if you want to start using web components in production, come to learn what features can you use today. Actually, despite the still short browser support, some of web components features seems to be the best choice to start with . The assessment you’ll learn is the reflection of my personal research and work on my spare time and also feedbacks from my co-workers.
- 1,218