A presentation at Devoxx Belgium in in Antwerp, Belgium by Horacio Gonzalez
WebComponents in 2023: A Complete Exploration Horacio Gonzalez 2023-10-02 #Devoxx #WebComponents
Who are we? Introducing myself and introducing OVHcloud #Devoxx #WebComponents
Horacio Gonzalez @LostInBrittany Spaniard Lost in Brittany #Devoxx #WebComponents
OVHcloud Web Cloud & Telcom 30 Data Centers in 12 locations 1 Million+ Servers produced since 1999 Private Cloud 34 Points of Presence on a 20 TBPS Bandwidth Network 1.5 Million Customers across 132 countries Public Cloud 2200 Employees worldwide 3.8 Million Websites hosting Storage 115K Private Cloud VMS running 1.5 Billion Euros Invested since 2016 300K Public Cloud instances running P.U.E. 1.09 Energy efficiency indicator 380K Physical Servers running in our data centers 20+ Years in Business Disrupting since 1999 Network & Security #Devoxx #WebComponents
We want the code! https://github.com/LostInBrittany/web-components-in-2023/ #Devoxx #WebComponents
What the heck are web component? The 3 minutes context #Devoxx #WebComponents
Web Components Web standard W3C #Devoxx #WebComponents
Web Components Available in all modern browsers: Firefox, Safari, Chrome #Devoxx #WebComponents
Web Components Create your own HTML tags Encapsulating look and behavior #Devoxx #WebComponents
Web Components Fully interoperable With other web components, with any framework #Devoxx #WebComponents
Web Components CUSTOM ELEMENTS SHADOW DOM #Devoxx #WebComponents TEMPLATES
Custom Element To define your own HTML tag <body> … <script> window.customElements.define(‘my-element’, class extends HTMLElement {…}); </script> <my-element></my-element> </body> #Devoxx #WebComponents
Shadow DOM To encapsulate subtree and style in an element <button>Hello, world!</button> <script> var host = document.querySelector(‘button’); const shadowRoot = host.attachShadow({mode:’open’}); shadowRoot.textContent = ‘こんにちは、影の世界!’; </script> #Devoxx #WebComponents
Template To have clonable document template <template id=”mytemplate”> <img src=”” alt=”great image”> <div class=”comment”></div> </template> var t = document.querySelector(‘#mytemplate’); // Populate the src at runtime. t.content.querySelector(‘img’).src = ‘logo.png’; var clone = document.importNode(t.content, true); document.body.appendChild(clone); #Devoxx #WebComponents
But in fact, itʼs just an element… ● ● ● ● Attributes Properties Methods Events #Devoxx #WebComponents
Sometimes I feel a bit grumpy The stories of the grumpy old speaker… #Devoxx #WebComponents
On Polymer tour since 2014 #Devoxx #WebComponents
Image: bu.edu Web components == Revolution #Devoxx #WebComponents
Images: BitRebels & Brickset Building a world brick by brick #Devoxx #WebComponents
Is the promise unfulfilled? It’s 2023 now, where is your revolution, dude? #Devoxx #WebComponents
Is it a conspiracy? #Devoxx #WebComponents
Am I only a dreamer? #Devoxx #WebComponents
Well, revolution IS there But it’s a silent one… #Devoxx #WebComponents
I as looking for a great example #Devoxx #WebComponents
New Reddit runs on Web Components #Devoxx #WebComponents
Often hidden in plain sight #Devoxx #WebComponents
Vanilla Web Components #Devoxx #WebComponents
Let’s build a vanilla Web Component Using only HTML, CSS & JS, no library needed #Devoxx #WebComponents
A very basic web component class HelloWorld extends HTMLElement { // This gets called when the HTML parser sees your tag constructor() { super(); // always call super() first in the ctor. this.msg = ‘Hello World!’; } // Called when your element is inserted in the DOM or // immediately after the constructor if it’s already in the DOM connectedCallback() { this.innerHTML = <p>${this.msg}</p>
; } } customElements.define(‘hello-world’, HelloWorld);
#Devoxx #WebComponents
Custom Elements: ● Let you define your own HTML tag with bundled JS behavior ● Trigger lifecycle callbacks ● Automatically “upgrade” your tag when inserted in the document #Devoxx #WebComponents
Custom Elements donʼt: ● Scope CSS styles ○ Shadow DOM ● Scope JavaScript ○ ES2015 ● “Reproject” children into <slot> elements ○ Shadow DOM #Devoxx #WebComponents
Adding ShadowDOM class HelloWithShadowdom extends HTMLElement { // This gets called when the HTML parser sees your tag constructor() { super(); // always call super() first in the ctor. this.msg = ‘Hello World from inside the ShadowDOM!’; this.attachShadow({ mode: ‘open’ }); } // Called when your element is inserted in the DOM or // immediately after the constructor if it’s already in the DOM connectedCallback() { this.shadowRoot.innerHTML = <p>${this.msg}</p>
; } } customElements.define(‘hello-with-shadowdom’, HelloWithShadowdom);
#Devoxx #WebComponents
Using web components <!DOCTYPE html> <html> <head> <title>Vanilla Web Components</title> <script src=”./hello-world.js”></script> <script src=”./hello-with-shadowdom.js”></script> </head> <body> <hello-world></hello-world> <hello-with-shadowdom></hello-with-shadowdom> </body> </html> #Devoxx #WebComponents
Using web components #Devoxx #WebComponents
Lifecycle callbacks class MyElementLifecycle extends HTMLElement { constructor() { // Called when an instance of the element is created or upgraded super(); // always call super() first in the ctor. } static get observedAttributes() { // Tells the element which attributes to observer for changes return []; } connectedCallback() { // Called every time the element is inserted into the DOM } disconnectedCallback() { // Called every time the element is removed from the DOM. } attributeChangedCallback(attrName, oldVal, newVal) { // Called when an attribute was added, removed, or updated } adoptedCallback() { // Called if the element has been moved into a new document } } #Devoxx #WebComponents
my-vanilla-counter element class MyVanillaCounter extends HTMLElement { constructor() { super(); this._counter = 0; this.attachShadow({ mode: ‘open’ }); } connectedCallback() { this.render(); this.display(); } static get observedAttributes() { return [ ‘counter’ ] } // We reflect attribute changes into property changes attributeChangedCallback(attr, oldVal, newVal) { if (oldVal !== newVal) { this[attr] = newVal; } } #Devoxx #WebComponents
my-counter custom element // Getter and setters for counter get counter() { return this._counter; } set counter(value) { if (value != this._counter) { this._counter = Number.parseInt(value); this.setAttribute(‘counter’, value); this.display(); } } increment() { this.counter = this.counter + 1; this.dispatchEvent(new CustomEvent(‘increased’, {detail: {counter: this.counter}})); } #Devoxx #WebComponents
my-counter custom element render() { let container = document.createElement(‘div’); container.style.display = ‘flex’; … this.style.fontSize = ‘5rem’; } display() { this.output.innerHTML = ${this.counter}
; } } customElements.define(my-vanilla-counter
, MyVanillaCounter);
#Devoxx #WebComponents
my-counter-with-templates let template = ` <style> … </style> <div class=”container”> <div id=”icon”> <img src=”${import.meta.url}/../img/logo.png”>
</div> <div id=”value”> 0 </div> </div> `; #Devoxx #WebComponentsmy-counter-with-templates render() { let templ = document.createElement(‘template’); templ.innerHTML = template; this.shadowRoot.appendChild(templ.content.cloneNode(true)); let button = this.shadowRoot.getElementById(‘icon’); button.addEventListener(‘click’, this.increment.bind(this)); } display() { console.log(this.shadowRoot.getElementById(‘value’)) this.shadowRoot.getElementById(‘value’).innerHTML = ${this.counter}
; }
#Devoxx #WebComponents
Coding my-counter #Devoxx #WebComponents
my-counter custom element #Devoxx #WebComponents
Why those libs? Why people don’t use vanilla? #Devoxx #WebComponents
Web component standard is low level At it should be! #Devoxx #WebComponents
Standard == basic bricks Standard exposes an API to: ○ Define elements ○ Encapsulate DOM #Devoxx #WebComponents
Libraries are helpers They give you higher-level primitives #Devoxx #WebComponents
Different high-level primitives Each one tailored to a use #Devoxx #WebComponents
Sharing the same base High-performant, low-level, in-the-platform web components standard #Devoxx #WebComponents
Libraries aren’t a failure of standard They happen by design #Devoxx #WebComponents
A library for building reusable, scalable component libraries #Devoxx #WebComponents
Not another library A Web Component toolchain #Devoxx #WebComponents
A build time tool To generate standard web components #Devoxx #WebComponents
Fully featured ● Web Component-based ● Component pre-rendering ● Asynchronous rendering pipeline ● Simple component lazy-loading ● TypeScript support ● JSX support ● Reactive Data Binding ● Dependency-free components #Devoxx #WebComponents
And the cherry on the cake Server-Side Rendering #Devoxx #WebComponents
Stencil leverages the web platform #Devoxx #WebComponents
The Stencil story A company tired of putting good code in the bin #Devoxx #WebComponents
Once upon a time there was a fight Between native apps and web app on mobile #Devoxx #WebComponents
A quest to the perfect solution Hybrid apps, leveraging on web technologies #Devoxx #WebComponents
A company wanted to do it well The perfect technology for mobile web and hybrid apps #Devoxx #WebComponents
The time is 2013 So what technology would you use? #Devoxx #WebComponents
Really soon after launch… Hey folks, we are killing AngularJS! #Devoxx #WebComponents
What did Ionic people do? Let’s put everything in the trash bin and begin anew #Devoxx #WebComponents
But times have changed… In 2013 Angular JS was the prom queen #Devoxx #WebComponents
Times have changed… In 2017 Angular is only one more in the clique #Devoxx #WebComponents
Angular limits adoption of Ionic Devs and companies are very vocal about JS Frameworks #Devoxx #WebComponents
What did Ionic people do? Let’s put everything in the trash bin and begin anew… But on which framework? #Devoxx #WebComponents
What about web components? A nice solution for Ionic problems: Any framework, even no framework at all! #Devoxx #WebComponents
But what Web Component library? SkateJS There were so many of them! #Devoxx #WebComponents
Let’s do something different A fully featured web component toolchain With all the bells and whistles! #Devoxx #WebComponents
Ionic rewrote all their code again From Ionic 4 is fully based on Stencil #Devoxx #WebComponents
Now Ionic works on any framework Or without framework at all #Devoxx #WebComponents
And we have Stencil To use it in any of our projects #Devoxx #WebComponents
Hands on Stencil Simply use npm init npm init stencil Choose the type of project to start ? Select a starter project. Starters marked as [community] are developed by the Stencil Community, rather than Ionic. For more information on the Stencil Community, please see https://github.com/stencil-community › - Use arrow-keys. Return to submit. ❯ component Collection of web components that can be used anywhere app [community] Minimal starter for building a Stencil app or website ionic-pwa [community] Ionic PWA starter with tabs layout and routes #Devoxx #WebComponents
Hands on Stencil And the project is initialized in some seconds! ✔ Pick a starter › component ✔ Project name › my-stencil-counter ✔ All setup in 17 ms $ npm start Starts the development server. $ npm run build Builds your components/app in production mode. $ npm test Starts the test runner. We $ $ $ suggest that you begin by typing: cd my-stencil-counter npm install npm start Happy coding! 🎈 #Devoxx #WebComponents
Let’s look at the code #Devoxx #WebComponents
Some concepts import { Component, Prop, h } from ‘@stencil/core’; import { format } from ‘../../utils/utils’; @Component({ tag: ‘my-component’, styleUrl: ‘my-component.css’, shadow: true }) export class MyComponent { @Prop() first: string; Decorators #Devoxx #WebComponents
Some concepts @Prop() first: string; @Prop() middle: string; @Prop() last: string; @State() nickname: string; Properties and States #Devoxx #WebComponents
Some concepts render() { return <div>Hello, World! I’m {this.getText()}</div>; } Asynchronous rendering using JSX #Devoxx #WebComponents
Some concepts @Prop() value: number; @Watch(value) valueChanged(newValue: boolean, oldValue: boolean) { console.log(The new value is ${newValue}, it was ${oldValue} before
); }
Watch #Devoxx #WebComponents
Some concepts @Event() actionCompleted: EventEmitter; someAction(message: String) { this.actionCompleted.emit(message); } @Listen(‘actionCompleted’) actionCompletedHandler(event: CustomEvent) { console.log(‘Received the custom actionCompleted event: ‘, event.detail); } Emitting events #Devoxx #WebComponents
Some concepts @Method() async sayHello() { this.hello = true; } render() { return ( <Host> <h2>{ this.hello ? Hello sthlm.js
: ”}</h2> </Host> ); }
Asynchronous public methods #Devoxx #WebComponents
Some concepts @Component({ tag: ‘my-component’, styleUrl: ‘my-component.css’, shadow: true }) export class MyComponent { Optional Shadow DOM #Devoxx #WebComponents
Coding my-stencil-counter #Devoxx #WebComponents
Simple. Fast. Web Components #Devoxx #WebComponents
Do you remember Polymer The first Web Component library #Devoxx #WebComponents
It is deprecated… And that means good news! #Devoxx #WebComponents
Let’s try to see clearer Let’s dive into Polymer history… #Devoxx #WebComponents
A tool built for another paradigm No web component support on browsers No React, Angular or Vue innovations #Devoxx #WebComponents
No so well suited for the current one The current platform is way more powerful The state of art has evolved #Devoxx #WebComponents
Let’s learn from its lessons The current platform is way more powerful The state of art has evolved #Devoxx #WebComponents
And let it rest… There will have no Polymer 4… #Devoxx #WebComponents
So Polymer as we know it is dead… But the Polymer Project is indeed alive! #Devoxx #WebComponents
But I have invested so much on it! What to do? #Devoxx #WebComponents
That’s why web components are top You can keep using all your Polymer components and create the new ones with a new library… And it simply works! #Devoxx #WebComponents
Born from the Polymer team For the new web paradigm #Devoxx #WebComponents
Modern lightweight web components For the new web paradigm #Devoxx #WebComponents
Based on lit-html An efficient, expressive, extensible HTML templating library for JavaScript #Devoxx #WebComponents
Do you know tagged templates? function uppercase(strings, …expressionValues) { var finalString = ” for ( let i = 0; i < strings.length; i++ ) { if (i > 0) { finalString += expressionValues[i - 1].toUpperCase() } finalString += strings[i] } return finalString } const expressions = [ ‘Sophia Antipolis’, ‘RivieraDev’, ‘Thank you’]; console.log(uppercaseJe suis à ${expression[0]} pour ${expression[1]}. ${expression[2]}!
Little known functionality of template literals #Devoxx #WebComponents
lit-html Templates
let myTemplate = (data) => html<h1>${data.title}</h1> <p>${data.body}</p>
;
Lazily rendered Generates a TemplateResult #Devoxx #WebComponents
It’s a bit like JSX, isn’t it? The good sides of JSX… but in the standard! #Devoxx #WebComponents
LitElement import { LitElement, html } from ‘lit-element’; // Create your custom component class CustomGreeting extends LitElement { // Declare properties static get properties() { return { name: { type: String } }; } // Initialize properties constructor() { super(); this.name = ‘World’; } // Define a template render() { return html<p>Hello, ${this.name}!</p>
; } } // Register the element with the browser customElements.define(‘custom-greeting’, CustomGreeting);
Lightweight web-components using lit-html #Devoxx #WebComponents
Coding my-lit-counter #Devoxx #WebComponents
Web Components & Frameworks Less “either/or” and more “both/and” #Devoxx #WebComponents
Compatibility is on Web Components side Web Components everywhere, baby! #Devoxx #WebComponents
They are the interoperable alternative Any framework… or no framework at all #Devoxx #WebComponents
You can have a single implementation And it simply works everywhere* #Devoxx #WebComponents
*React don’t fully support them yet Long story made short: use lit-labs/react #Devoxx #WebComponents
When you need interoperability Nothing beats the standard #Devoxx #WebComponents
Angular can generate web components Angular Elements #Devoxx #WebComponents
Vue can generate web components With defineCustomElement() #Devoxx #WebComponents
React can generate web components But it can generate them too #Devoxx #WebComponents
What about Svelte? Let’s look in detail one case #Devoxx #WebComponents
Web Components & Design Systems One of the best cases for Web Components #Devoxx #WebComponents
So, what are Design Systems? And why should I look at them? #Devoxx #WebComponents
A talk for devs by a dev I am not a designer, neither I play one on TV… #Devoxx #WebComponents
The same or different? #Devoxx #WebComponents
Style Guides A document listing the styles, patterns, practices, and principles of a brand design standards #Devoxx #WebComponents
Style Guides Style guides define the applicationʼs look and feel #Devoxx #WebComponents
Style Guide Example: Uber https://brand.uber.com/ #Devoxx #WebComponents
Style Guide Example: Medium https://www.behance.net/gallery/7226653/Medium-Brand-Development #Devoxx #WebComponents
Style Guides alone are ambiguous Interpretation needed to adapt the preconisation to the use case #Devoxx #WebComponents
Component Catalogs A component catalog is a repository of components, with one or several implementations, code examples and technical documentation #Devoxx #WebComponents
Component Catalog example: Bootstrap https://getbootstrap.com/ #Devoxx #WebComponents
Component Catalog Example: ING’s Lion https://lion-web-components.netlify.app/ #Devoxx #WebComponents
Catalogs alone create inconsistency Like using the same LEGO bricks to create very different objects #Devoxx #WebComponents
Design Systems A Design System is like a common visual language for product teams #Devoxx #WebComponents
Design systems A Design System is a set of design standards, documentations, and principles, alongside with the toolkit (UI patterns and code components) to achieve those standards #Devoxx #WebComponents
Design systems #Devoxx #WebComponents
Example: Carbon Design System https://www.carbondesignsystem.com/ #Devoxx #WebComponents
Example: Firefox’s Photon Design System https://design.firefox.com/photon/ #Devoxx #WebComponents
Example: Material Design https://material.io/ #Devoxx #WebComponents
The component catalog The poor relative of the Design System family #Devoxx #WebComponents
Let’s choose a simple example Bootstrap based component catalogs #Devoxx #WebComponents
A long time ago Components defined in HTML, CSS and some jQuery #Devoxx #WebComponents
Then it was AngularJS time… And new reference implementations were needed #Devoxx #WebComponents
But you know the sad story… All UI Bootstrap based catalogs woke up with an obsolete implementation #Devoxx #WebComponents
Worry no more, let’s do Angular! ng-bootstrap to the rescue #Devoxx #WebComponents
But times had changed… In 2017 Angular is only one more in the clique #Devoxx #WebComponents
TM React is the new Big Thing So let’s build React Bootstrap… #Devoxx #WebComponents
Wait, what about Vue? We also need BootstrapVue #Devoxx #WebComponents
OK, I think you see my point… #Devoxx #WebComponents
Most Design System do a choice Either they choose a canonical implementation or they ship and maintain several implementations #Devoxx #WebComponents
Both choices are problematic Shipping only one implementation: Web dev ecosystem changes quickly and almost nobody keeps the same framework for years… #Devoxx #WebComponents
Both choices are problematic Shipping several implementations: You need to maintain all the implementation… and you still miss some others #Devoxx #WebComponents
Incomplete catalogs are problematic People will need to recode the components in their chosen framework… Coherence is not guaranteed!!! #Devoxx #WebComponents
Example: Carbon Design System #Devoxx #WebComponents
Web Components & Design Systems A match made in heaven #Devoxx #WebComponents
Compatibility is on Web Components side Web Components everywhere, baby! #Devoxx #WebComponents
Do you remember AngularJS? And all the code put in the trash bin when Angular arrived… #Devoxx #WebComponents
The pain of switching frameworks? Rewriting once again your code… #Devoxx #WebComponents
The impossibility of sharing UI code? Between apps written with different frameworks #Devoxx #WebComponents
Web Components change that In a clean and standard way #Devoxx #WebComponents
They are the interoperable alternative Any framework… or no framework at all #Devoxx #WebComponents
They are truly everywhere 🚀 🚀 Even in the spaaaaaaaace 🚀 #Devoxx #WebComponents
You can have a single implementation And it simply works everywhere #Devoxx #WebComponents
When you need interoperability Nothing beats the standard #Devoxx #WebComponents
But how to do it? Designing, developing and managing a catalog of Web Components #Devoxx #WebComponents
Learning from the best https://lion-web-components.netlify.app/ #Devoxx #WebComponents
Learning from the best https://github.com/CleverCloud/clever-components #Devoxx #WebComponents
What kind of components? From little atomic blocs to big smart components, and everything in between #Devoxx #WebComponents
A matter of size and complexity What kind(s) of components you want to build #Devoxx #WebComponents
Build from the bottom and go up Eat your own dog food #Devoxx #WebComponents
And how to choose the atoms? Flexibility and configurability are key #Devoxx #WebComponents
And how to choose the atoms? Encode often used patterns #Devoxx #WebComponents
And what about the molecules? Capitalize on your atoms Keep the flexibility and configurability #Devoxx #WebComponents
Big smart business components Encoding your business logic #Devoxx #WebComponents
Internal or external customers? Who are your target users? #Devoxx #WebComponents
Internal customers need off-the-shelf components A well defined and coherent look-and-feel #Devoxx #WebComponents
External customers need to be able to tweak Theming and customizing components #Devoxx #WebComponents
How to organize the catalog Packages, imports and pragmatism #Devoxx #WebComponents
A single repository Single source of truth for the catalog #Devoxx #WebComponents
Two schools of thought A packet per component or a global one #Devoxx #WebComponents
Two schools of thought Individual versioning vs global one #Devoxx #WebComponents
Driving-up adoption Making devs use your components #Devoxx #WebComponents
Think who are your target users Users of any framework current or future… #Devoxx #WebComponents
They aren’t used to your library And they shouldn’t need to be #Devoxx #WebComponents
Go the extra mile to drive up adoption So they don’t need to do it #Devoxx #WebComponents
Make it easy to use As easy as a HTML tag #Devoxx #WebComponents
Document every composant How to use, inputs/outputs, examples… #Devoxx #WebComponents
Documentation isn’t enough Storybook make adoption easy #Devoxx #WebComponents
Keeping a coherent writing style Write down your guidelines #Devoxx #WebComponents
I18n shouldn’t be an afterthought Prepare everything for internationalization #Devoxx #WebComponents
That’s all, folks! Thank you all! #Devoxx #WebComponents
For almost a decade now, we’ve been hearing about Web Components and their appealing promise of finally basing web development on a true component architecture, promoting reusability, modularization, and encapsulation. However, it is clear that today, in 2023, this promise is still not entirely fulfilled. Frameworks like React, Angular, and Vue continue to dominate the spotlight while the discourse around Web Components remains almost inaudible. Yet, Web Components are now present in many websites and applications we use every day, without us even noticing. The revolution is indeed underway, albeit rather quietly. In this lab, we will delve into the current evolution of Web Components, examining in detail the main libraries (Lit, Stencil, Hybrid…) and open-source component catalogs (Material, Lion, OpenUI5, Wired…) We will explore how different frameworks such as Svelte, Vue, and Angular have integrated and managed Web Components. The session aims to provide a comprehensive overview of strategies for creating reusable, framework-independent web components. We will also address common challenges, such as compatibility issues and Server Side Rendering (SSR) management, and the best practices and solutions for overcoming these problems.