Web Components
The old new era
Why?
- HTML is not verbose/"semantic" enough.
- There is no standard template system.
- There is no native encapsulation in browsers.
- There is no way to reuse existing HTML.
- Everything is a component, right?
- WE LOVE DECLARATIVE WEB!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!111111111one
Need for verbosity
- HTML is semantic only for end user.
- Developers want to be able to read their code.
- The era of "developer semantics".
Need for verbosity
<article>
<h2>Slider</h2>
<section style="top: 330px; display: none; ">
<h3>Slide</h3>
<img src="slide.svg" alt="The beautifully beautiful slide!">
</section>
</article>
vs
<x-slider>
<x-slide>
<x-slide-title>Slide</x-slide-title>
<x-slide-image src="slide.svg">The beautifully beautiful slide!</x-slide-image>
</x-slide>
</x-slider>
Custom elements!
- Emerging standard for creating our own tags with semantics defined by us.
- Easy way to extend existing tags.
- Element's lifecycles.
- Live detection and enhancement of custom elements.
- Forced to use special name convention – prefix-name.
New custom element
class XSlider extends HTMLElement {}
window.customElements.define( 'x-slider', XSlider );
<x-slider></x-slider>
Extending existing element
class XButton extends HTMLButtonElement {}
window.customElements.define( 'x-button', XButton, { extends: 'button' } );
<button is="x-button"></button>
Native template system
- All existing template systems are string-based…
- …but DOM is a tree.
- How to utilize tree strenghts in templates?
- How to "switch off" some DOM subtrees (e.g. force them not to fetch images)?
template
-
template contains inactive DOM subtree.
- Only inserting its content into some "live" site's element activates this subtree.
- What's more, template just reuses good old DocumentFragment!
Working with template
<template id="image">
<img src="" alt="">
</template>
<div id="image-container"></div>
const template = document.getElementById('image').content;
const img = template.querySelector( 'img' );
img.src = '/whatever.png';
img.alt = 'Just a placeholder.';
const parsed = document.importNode( template, true );
document.getElementById( 'image-container' ).appendChild( parsed );
Need for encapsulation
- HTML & CSS are leaky by default.
- Everything exists in a global scope.
- Everything is interacting with everything.
- There is no way to hide implementation details (video tag case).
- BEM is helping, but it's merely a convention.
The shadow boundary
It hides all implementation details.
All styles inside it are scoped.
Nothing is exposed to the Light DOM…
…so we are forced to create sane API.
Light DOM vs Shadow DOM
<x-collapsible>
<button>Collapse</button>
<div>
<p>Some content</p>
</div>
<script>button.onclick = collapseDiv;</script>
</x-collapsible>
vs
<x-collapsible>
<p>Some content</p>
</x-collapsible>
More complicated example
Slots
- Slots are just placeholders.
- They wait for our content.
- It has a fancy name: "Nodes Distribution Algorithm".
HTML as a module
- We can reuse JS by modularizing it and using script tag.
- We can reuse CSS by putting it into the separate file.
- For the very long time the only way to do this with HTML was using an iframe.
HTML Imports
Just put your component into separate file:
<style>[…]</style>
<script>[…]</script>
And import it from your application's main file:
<link rel="import" href="component.html">
HTML Imports and ES Modules
- They are able to coexist…
- …but they are two very similar mechanisms, yet totally separate.
- Will HTML Imports become a subtype of ES Modules?
Standarization
- The main goal is to upstream every WC part into DOM and/or HTML standard…
- …which is already partly done.
Current browser support
- Can I Use lies!
- Only Chrome supports custom elements – but in their former version.
- Only Chrome supports Shadow DOM – in its former and current versions.
- Only Chrome is even willing to support HTML Imports…
- Still in flux – after 3 years.
- Better go React then!
- Polymer? Nope!
Common pitfalls
- Not everything is a component…
- …at least not a declarative one!
- Non-UI related logic inside custom tags? Bah!
2 pillars of architecture
- Totally independent UI, created with the use of web components.
- Business/application/non-UI logic, created with… PURE JS™.
- Events as the way to communicate between these two separate worlds.
- Just like in Zakas's idea.
Web Components
The old new era