Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
When to use web components
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Tim van der Lippe
February 16, 2018
Programming
3
350
When to use web components
My presentation at the FrontendDeveloperLove 2018 conference
Tim van der Lippe
February 16, 2018
Tweet
Share
Other Decks in Programming
See All in Programming
Fragmented Architectures
denyspoltorak
0
150
Patterns of Patterns
denyspoltorak
0
1.4k
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
5
1k
0→1 フロントエンド開発 Tips🚀 #レバテックMeetup
bengo4com
0
560
Smart Handoff/Pickup ガイド - Claude Code セッション管理
yukiigarashi
0
130
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
Vibe Coding - AI 驅動的軟體開發
mickyp100
0
170
AIと一緒にレガシーに向き合ってみた
nyafunta9858
0
180
CSC307 Lecture 09
javiergs
PRO
1
830
プロダクトオーナーから見たSOC2 _SOC2ゆるミートアップ#2
kekekenta
0
200
CSC307 Lecture 04
javiergs
PRO
0
660
OSSとなったswift-buildで Xcodeのビルドを差し替えられるため 自分でXcodeを直せる時代になっている ダイアモンド問題編
yimajo
3
610
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
430
Deep Space Network (abreviated)
tonyrice
0
47
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
60
42k
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
210
Paper Plane
katiecoart
PRO
0
46k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
300
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
130
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
0
200
Technical Leadership for Architectural Decision Making
baasie
1
240
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
160
So, you think you're a good person
axbom
PRO
2
1.9k
Transcript
When to use web components Tim van der Lippe TimvdLippe
Remote Polymer team member Master student Computer Science Delft University
of Technology
3 accepted standards
Schedule Accepted standards • <template> • Shadow DOM • Custom
Elements Examples
<template> element
Blueprint <template> <header> TODOList: </header> <span>Presentation at: <a href="https://www.frontenddeveloperlove.com/" >FrontendDevelopersLove</a>
</span> </template>
Dynamically creating DOM
Dynamically creating DOM node.innerHTML = ` <header> TODOList: </header> <span>Presentation
at: <a href="https://www.frontenddeveloperlove.com/" >FrontendDevelopersLove</a> </span> `
Dynamically creating DOM const header = document.createElement('header'); header.innerText = `TODOList`;
const span = document.createElement('span'); const a = document.createElement('a'); a.href = `https://www.frontenddeveloperlove.com/`; a.innerText = `FrontendDevelopersLove`; span.appendChild(document.createTextNode('Presentation at:')) span.appendChild(a) node.appendChild(header); node.appendChild(span);
Performance problems Parsing (innerHTML)
Performance problems Creation of JS nodes (document.createElement)
Performance problems DOM manipulation (all)
Dynamically creating DOM const template = document.createElement('template'); template.innerHTML = `
<header> TODOList: </header> <span>Presentation at: <a href="https://www.frontenddeveloperlove.com/" >FrontendDevelopersLove</a> </span>`; node.appendChild(template.content.cloneNode(true));
https://jsperf.com/clonenode-vs-createelement-performance/95 Method Ops/sec Relative speed innerHTML 22,828 32% createElement 31,566
45% createElement (abstraction) 25,440 36% template.content.cloneNode 69,874 100%
When to use <template> Creating DOM based on the same
“template” (e.g. component) Efficiently update DOM after the fact (lit-html) Only creating DOM once “template” only consists of dynamic parts
Shadow DOM
Native elements have encapsulation http://techslides.com/demos/sample-videos/small.mp4
Native elements have encapsulation http://techslides.com/demos/sample-videos/small.mp4
Native elements have encapsulation CSS rules do not reach into
shadow DOM Hide implementation details
CSS scoping/encapsulation Naming convention (BEM)
CSS scoping/encapsulation Runtime class generation (styled-components)
CSS scoping/encapsulation None (and pray)
User-exposed Shadow DOM const div = document.createElement('div'); div.attachShadow({mode: 'open'}); div.shadowRoot.innerHTML
= ` <style> span { color: red; } </style> <span>In Shadow DOM</span>` document.body.appendChild(div); https://dom.spec.whatwg.org/#dom-element-attachshadow
User-exposed Shadow DOM const div = document.createElement('div'); div.attachShadow({mode: 'open'}); div.shadowRoot.innerHTML
= ` <style> span { color: red; } </style> <span>In Shadow DOM</span>` document.body.appendChild(div); https://dom.spec.whatwg.org/#dom-element-attachshadow
User-exposed Shadow DOM const div = document.createElement('div'); div.attachShadow({mode: 'open'}); div.shadowRoot.innerHTML
= ` <style> span { color: red; } </style> <span>In Shadow DOM</span>` document.body.appendChild(div); https://dom.spec.whatwg.org/#dom-element-attachshadow
User-exposed Shadow DOM const div = document.createElement('div'); div.attachShadow({mode: 'open'}); div.shadowRoot.innerHTML
= ` <style> span { color: red; } </style> <span>In Shadow DOM</span>` document.body.appendChild(div); https://dom.spec.whatwg.org/#dom-element-attachshadow
Other (implementation) benefits Cheap style invariance checks Simple CSS selectors
When to use Shadow DOM Encapsulate DOM to prevent taint
by global CSS Hide implementation details Overusing Shadow DOM
Custom Elements
Team Parkour Research + prototype team Alex Russell Polymer Summit
2017 https://www.youtube.com/watch?v=y-8Lmg5Gobw
Team Parkour State-of-the-art back then Alex Russell Polymer Summit 2017
https://www.youtube.com/watch?v=y-8Lmg5Gobw
Team Parkour Identify areas that are common Alex Russell Polymer
Summit 2017 https://www.youtube.com/watch?v=y-8Lmg5Gobw
Component model $.widget('ui.menu', { defaultElement: '<ul>', options: { role: 'menu'
}, _create: function() { this.activeMenu = this.element; this._addClass('ui-menu', 'ui-widget ui-widget-content'); }
Component model goog.ui.MenuItem = function(content, opt_model, opt_domHelper, opt_renderer) { goog.ui.Control.call(
this, content, opt_renderer || goog.ui.MenuItemRenderer.getInstance(), opt_domHelper) this.setValue(opt_model); } goog.inherits(goog.ui.MenuItem, goog.ui.Control);
Dojo dojo.declare('dijit.MenuItem' [dijit._Widget, dijit._Templated, dijit._Contained], { // Summary: A line
item in a Menu Widget } )
Angular React Vue ngOnInit constructor created ngAfterContentChecked componentDidMount mounted ngOnDestroy
componentWillUnmount destroyed ngOnChanges componentDidUpdate updated
Angular React Vue ngOnInit constructor created ngAfterContentChecked componentDidMount mounted ngOnDestroy
componentWillUnmount destroyed ngOnChanges componentDidUpdate updated Native constructor connectedCallback disconnectedCallback attributeChangedCallback
https://xkcd.com/927/
Investigated improvements HTML & DOM JS CSS Custom Elements Classes
CSS Variables <template> Promise Web animations Shadow DOM async/await
Browser standards • •
class HelloWorld extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = 'Hello World!'; } connectedCallback() { console.log('connected!'); } disconnectedCallback() { console.log('disconnected'); } }; customElements.define('hello-world', HelloWorld); <hello-world> </hello-world>
class HelloWorld extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = 'Hello World!'; } connectedCallback() { console.log('connected!'); } disconnectedCallback() { console.log('disconnected'); } }; customElements.define('hello-world', HelloWorld); <hello-world> </hello-world>
class HelloWorld extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = 'Hello World!'; } connectedCallback() { console.log('connected!'); } disconnectedCallback() { console.log('disconnected'); } }; customElements.define('hello-world', HelloWorld); <hello-world> </hello-world>
class HelloWorld extends HTMLElement { constructor() { super(); this.attachShadow({mode: 'open'});
this.shadowRoot.innerHTML = 'Hello World!'; } connectedCallback() { console.log('connected!'); } disconnectedCallback() { console.log('disconnected'); } }; customElements.define('hello-world', HelloWorld); <hello-world> </hello-world>
When to use Custom Elements Components on the web (without
libraries) Base layer for library authors Interoperability between components Solutions that do not require a component
Combine together
<profile-picture picture="TimvdLippe"> </profile-picture>
const template = document.createElement('template'); template.innerHTML = ` <style>img { border-radius:
50%; }</style> <img src="domain.com/fallback.png" /> `; class ProfilePicture extends HTMLElement{ constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); this._image = this.shadowRoot.querySelector('img'); } static get observedAttributes() { return ['picture']; } attributeChangedCallback(name, oldValue, newValue) { this._image.src = `domain.com/${newValue}.png`; } } customElements.define('profile-picture', ProfilePicture);
const template = document.createElement('template'); template.innerHTML = ` <style>img { border-radius:
50%; }</style> <img src="domain.com/fallback.png" /> `; class ProfilePicture extends HTMLElement{ constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); this._image = this.shadowRoot.querySelector('img'); } static get observedAttributes() { return ['picture']; } attributeChangedCallback(name, oldValue, newValue) { this._image.src = `domain.com/${newValue}.png`; } } customElements.define('profile-picture', ProfilePicture);
const template = document.createElement('template'); template.innerHTML = ` <style>img { border-radius:
50%; }</style> <img src="domain.com/fallback.png" /> `; class ProfilePicture extends HTMLElement{ constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); this._image = this.shadowRoot.querySelector('img'); } static get observedAttributes() { return ['picture']; } attributeChangedCallback(name, oldValue, newValue) { this._image.src = `domain.com/${newValue}.png`; } } customElements.define('profile-picture', ProfilePicture);
const template = document.createElement('template'); template.innerHTML = ` <style>img { border-radius:
50%; }</style> <img src="domain.com/fallback.png" /> `; class ProfilePicture extends HTMLElement{ constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); this._image = this.shadowRoot.querySelector('img'); } static get observedAttributes() { return ['picture']; } attributeChangedCallback(name, oldValue, newValue) { this._image.src = `domain.com/${newValue}.png`; } } customElements.define('profile-picture', ProfilePicture);
const template = document.createElement('template'); template.innerHTML = ` <style>img { border-radius:
50%; }</style> <img src="domain.com/fallback.png" /> `; class ProfilePicture extends HTMLElement{ constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); this._image = this.shadowRoot.querySelector('img'); } static get observedAttributes() { return ['picture']; } attributeChangedCallback(name, oldValue, newValue) { this._image.src = `domain.com/${newValue}.png`; } } customElements.define('profile-picture', ProfilePicture);
Webcomponent libraries
https://timvdlippe.github.io/react-imgpro/ Based on https://github.com/nitin42/react-imgpro
“And React's component based model was perfect for hiding all
the implementation details in a component”
And Web component based model was perfect for hiding all
the implementation details in a component
Straightforward translation componentDidMount connectedCallback JSX <template> defaultProps observedAttributes
Conclusion
We talked about <template> Shadow DOM Custom Elements
Interoperability
When to use web components <template> Shadow DOM Custom Elements
TimvdLippe