Web Components hacen el Camino de Santiago

Marcela Gotta

Expert Frontend Developer, Sngular

¿Los Web Components son tu camino?

Marcela Gotta

Expert Frontend Developer, Sngular

01. Presentación e introducción

¿Los Webcomponents son tu camino?

En mis tiempos todo esto era campo

¿Los Web Components son tu camino?

Hola! soy Marcela Gotta

Expert Software Developer en Sngular con más de 10 años de experiencia en el desarrollo de aplicaciones trabajando para empresas como BBVA, ING, Carrefour, Mapfre o el Corte Inglés, entre otras. Amante del desarrollo Front-end y el diseño UX, especialista en JavaScript con experiencia trabajando con las tecnologías más destacadas de su ecosistema, como Angular, React, Vue.js, Node.js y LitElement.

Una Web Renovada

  • Web Components

  • PWA

  • WebRTC

  • WebXR

  • WebAssembly

Características que nunca pensamos tener

  • WebSocket

  • WebWorkers

  • ServiceWorkers

  • WebGL

  • ¡Y mucho más!

Nuestro protagonista:

Web Components

¡Muchas preguntas!

¿Qué son Web Components?

¿Cómo funcionan?

¿Cómo podemos crear Web Components?

¿Para qué sirven?

¿Quiénes somos?

¿Por qué existimos?

¿Valen la pena?

02. Historia de la Web

¿Los Webcomponents son tu camino?

Hagamos un viaje al pasado

El nacimiento de La Web

Funciona en los navegadores e internet a través de hipervinculos y conexión entre servidores

Text

Los tres mosqueteros de La Web

HTML

Javascript

CSS

Son las tres tecnologías top en el mundo web.

Los materiales para construir tu aplicación.

Gracias a ellos y los avances que han tenido estas tecnologías, la web es como la conocemos.

La Web humanizada

En un principio todo era oscuro

En el inicio de la web solo era una herramienta que permita acceder a diferentes archivos a través de hipervinculos e internet. Javascript ni CSS existían y HTML casí no tenía funcionalidades.

¡Y se hizo la luz!

La web se hizo más popular y con más características, css y javascript aparecieron también la web 2.0 interconectada entre ordenadores y servidores.

Apareció la web 2.0

03. La era de los frameworks

¿Los Webcomponents son tu camino?

La Web gana popularidad y con ello las cosas se complican

La evolución del Front End

El stack actual del Front End

¿Frontend o Microfrontend?

Las tecnologías más populares tienen algo en común...

¡Tienen una arquitectura basada en componentes!

04. ¿Qué son componentes?

¿Los Webcomponents son tu camino?

¿Necesitamos componentes?

¡La web ya NO es como antes!

Los avances en el área hace importante la arquitectura.

Gracias a los avances que han tenido estas tecnologías, la web es como la conocemos!

Crear sitios web se complica

Piezas de código reutilizable

Construimos nuestra casa virtual

Conectamos la casa para darle vida.

Planificamos qué es lo mejor para el tipo de casa que queremos ;)

Las piezas de la casa son reutilizables.

Construimos la estructura con estas piezas

¿Qué son 

componentes?

  • Una pieza de código independiente.
  • Es personalizado
  • Es reutilizable
  • Su comportamiento es 100% configurable.

Arquitectura basada en componentes

 Nuestros componentes son piezas reutilizables

Estas piezas están encapsuladas y pueden ser

Se encargan de pintar nuestros componentes sin tener que preocuparse de alguna lógica de negocio.

Se encargan de transformar la lógica de negocio, construir cómo mostrar nuestras piezas y manejar el estado.

Visuales

Lógicos

05. Problemas de los componentes

¿Los Webcomponents son tu camino?

1. Ecosistema tecnológico extenso

Existe una alta oferta de librerías y frameworks en Javascript. Una heladería con muchos sabores.

2. El desarrollo web se complica

Al haber tantas ofertas con diversos pros y contras es complicado aprender y especializarse en alguna de ellas.

3. Son dependientes a los frameworks

Los componentes dependen de las librerías y frameworks. Cada vez que cargues un componente de una librería que no tengas agregada, deberás hacerlo, lo que agregará tamaño al proyecto.

4. Debemos elegir un solo stack

Se tiende a elegir un solo framework por proyecto, así los componentes serán creados en una sola tecnología por lo que si deseas hacer otro proyecto con otra tecnología tendrás que rehacer parte del código.

06. La solución: Web Components

¿Los Webcomponents son tu camino?

¿Qué son Web Components?

Componentes nativos, independientes y reutilizables.

Componentes vs Web Components

Los Web Componentes son un tipo de componentes que cumplen ciertas espeficaciones y funcionan bajo un entorno nativo.

Los Web Components se basan en 4 especificaciones

Custom Elements

Puedes diseñar y utilizar nuevos tipos de elementos en el DOM

class MySearch extends HTMLElement {...}
customElements.define("my-search", MySearch);

Shadow DOM

Permite encapsular estilos CSS y HTML de tu componente.

constructor() {
  super();
  this.attachShadow({ mode: "open" });
}

ES Module

Te permite exportar, importar y reutilizar documentos JS bajo un estándar sencillo y modular.

export class MySearch extends HTMLElement {...}
import { MySearch } from "./src/MySearch.js";

HTML Template

Define cómo declarar fragmentos de HTML que no se cargan en la página hasta que son instanciados.

const template = document.createElement("template");
template.innerHTML = `<p>Soy un párrafo</p>`

Ventajas de los Web Components

  • Reutilización
  • Legibilidad
  • Mantenibilidad
  • Natividad
  • Consistencia

Desventajas de los WebComponents

  • Cuando se trata de desarrollar web complejas.
  • El código generado dificil de leer.
  • Necesita de un Polyfill

07. ¿Cómo crear un Web Component?

¿Los Webcomponents son tu camino?

Cosas a tener en cuenta

  • Conocimientos de HTML, CSS y Javascript.
  • Antes de empezar crear, ten un diseño a mano.

Nuestro Web Component

En esta ocasión vamos a crear un componente de tipo input con botón.

Soy un botón

Soy un input

Soy un label

Partes de un Web Component

Classes

Properties

Attributes

Methods

Events

Template

Template HTML

getTemplate() {
  const template = document.createElement("template");
  template.innerHTML = `
    <style>
      ${this.getStyles()}
    </style>
    <label part="label">${this.label}</label>
    <input 
      type="text" 
      value="${this.value}" 
      placeholder="${this.placeholder}"
      part="input" 
    />
    <button part="button">
        <slot>${this.button}</slot>
    </button>
  `;
  return template;
}

Propiedades y atributos

<my-search value="hello world" name="my name"></my-search>

static get observedAttributes() {
  return ["button", "label", "placeholder", "value"];
}

attributeChangedCallback(name, oldVal, newVal) {
  if (oldVal === newVal) {
    return;
  }

  this[name] = newVal;
}

Enviar y capturar eventos

dispatchCustomEvent(eventName, detail) {
  this.dispatchEvent(
    new CustomEvent(eventName, {
      bubbles: true,
      composed: true,
      detail,
    })
  );
}
addEventListeners() {
  this.buttonEl.addEventListener("click", () => { 
    this.dispatchCustomEvent("my-search-button-click", {
      button: this.button || this.innerHTML,
      value: this.value,
    })
  });

  this.inputEl.addEventListener("input", () => {
    this.dispatchCustomEvent("my-search-input-change", {
      value: this.inputEl.value,
    });
  });
}
connectedCallback() {
  this.addEventListeners();
}

Ciclo de vida de un WebComponent

constructor()

connectedCallback()

attributeChangedCallback()

disconnectedCallback()

adoptedCallback()

Estilos de nuestro Web Component

Podemos agregar estilos CSS:

  • Estilos en linea
  • Agregando un bloque css dentro del mismo componente.
  • Librerías que facilitan esto
getStyles() {
  return `
    :host {
      display: block;
      font-family: sans-serif;
      font-weight: 300;
      font-size: 1rem;
      margin: 0.7rem 0;
    }

    input {
      border: none;
      border-bottom: 1px solid var(--my-search-input-border-color, #ccc);
      padding: 0.5rem;
    }

    label {
      display: block;
      padding-left: 0.5rem;
      font-size: 0.8rem;
    }

    button {
      border: none;
      background-color: #5f3993;
      cursor: pointer;
      outline: none;
      color: white;
      padding: 10px;
      border-radius: 5px;
      min-width: 6rem;
      min-height: 2rem;
    }

    button:hover {
      background-color: #9f7fcd;
    }

    button:active, button:focus {
      background-color: #472b6e;
    }
  `;
}

<style>
   ${this.getStyles()}
</style>

Código de nuestro Web Component

export class MySearch extends HTMLElement {
  static get observedAttributes() {
    return ["button", "label", "placeholder", "value"];
  }

  constructor() {
    super();
    this.attachShadow({ mode: "open" });
  }

  connectedCallback() {
    this.render();

    this.buttonEl = this.shadowRoot.querySelector("button");
    this.slotNode = this.buttonEl.querySelector("slot");
    this.inputEl = this.shadowRoot.querySelector("input");

    this.addEventListeners();
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    this.removeEventListeners();
  }

  get button() {
    return this.getAttribute("button") || "";
  }

  set button(data) {
    this.setAttribute("button", data);
  }

  get value() {
    return this.getAttribute("value") || "";
  }

  set value(data) {
    this.setAttribute("value", data);
  }

  get placeholder() {
    return this.getAttribute("placeholder") || "";
  }

  set placeholder(data) {
    this.setAttribute("placeholder", data);
  }

  get label() {
    return this.getAttribute("label") || "";
  }
  
  set label(data) {
    this.setAttribute("label", data); 
  }

  attributeChangedCallback(name, oldVal, newVal) {
    if (oldVal === newVal) {
      return;
    }

    this[name] = newVal;
  }

  addEventListeners() {
    this.buttonEl.addEventListener("click", () => { 
      this.dispatchCustomEvent("my-search-button-click", {
        button: this.button || this.innerHTML,
        value: this.value,
      })
    });

    this.inputEl.addEventListener("input", () => {
      this.dispatchCustomEvent("my-search-input-change", {
        value: this.inputEl.value,
      });
    });
  }

  removeEventListeners() {
    this.buttonEl.removeEventListener("click", () => {});
    this.inputEl.removeEventListener("input", () => {});
  }

  dispatchCustomEvent(eventName, detail) {
    this.dispatchEvent(
      new CustomEvent(eventName, {
        bubbles: true,
        composed: true,
        detail,
      })
    );
  }

  getTemplate() {
    const template = document.createElement("template");
    template.innerHTML = `
      <style>
        ${this.getStyles()}
      </style>
      <label part="label">${this.label}</label>
      <input 
        type="text" 
        value="${this.value}" 
        placeholder="${this.placeholder}"
        part="input" 
      />
      <button part="button">
          <slot>${this.button}</slot>
      </button>
    `;
    return template;
  }

  getStyles() {
    return `
      :host {
        display: block;
        font-family: sans-serif;
        font-weight: 300;
        font-size: 1rem;
        margin: 0.7rem 0;
      }

      input {
        border: none;
        border-bottom: 1px solid var(--my-search-input-border-color, #ccc);
        padding: 0.5rem;
      }

      label {
        display: block;
        padding-left: 0.5rem;
        font-size: 0.8rem;
      }

      button {
        border: none;
        background-color: #5f3993;
        cursor: pointer;
        outline: none;
        color: white;
        padding: 10px;
        border-radius: 5px;
        min-width: 6rem;
        min-height: 2rem;
      }

      button:hover {
        background-color: #9f7fcd;
      }

      button:active, button:focus {
        background-color: #472b6e;
      }
    `;
  }

  render() {
    this.shadowRoot.appendChild(this.getTemplate().content.cloneNode(true));
  }
}

Definir nuestro Web Component

Para agregar un Web Component debes definirlo en el documento HTML de tu página web.

import { MySearch } from "./src/MySearch.js";

window.customElements.define("my-search", MySearch);

Publicar WebComponents

  1. Crear un package.json
  2. Tener cuenta de npm y publicarlo con comandos.
{
    "name": "@marsgotta/my-search",
    "description": "Webcomponent my-search following open-wc recommendations",
    "license": "MIT",
    "author": "Mars Gotta",
    "version": "0.0.0",
    "main": "index.js",
    "module": "index.js",
    "scripts": {
      "analyze": "cem analyze --litelement",
      "start": "web-dev-server"
    },
    "devDependencies": {
      "@custom-elements-manifest/analyzer": "^0.4.17",
      "@web/dev-server": "^0.1.25"
    },
    "eslintConfig": {
      "root": true,
      "env": {
        "node": true
      },
      "rules": {}
    },
    "customElements": "custom-elements.json"
  }
$ npm login
$ npm publish

¿Se puede atravesar el Shadow DOM?

Sí, siempre que el desarrollador lo permita

  1. Custom properties CSS
  2. CSS Parts
  3. Atributos y propiedades del componente
  4. ¿Accediendo al shadow root desde el DOM?

Repositorio con demo

Puedes ver el WebComponents y ejemplos de implementación de este en Angular, Vue y React en este repositorio

08. Uso en diferentes entornos

¿Los Webcomponents son tu camino?

Web Components en Nativo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Native Search WebComponent</title>
    <script type="module" src="../my-search.js"></script>
</head>
<body>
    <my-search 
        value="Hello World" 
        label="I'm a label"
        button="I'm a button"
    >
  	</my-search>
    <style>
    <script type="module">
        document.querySelectorAll('my-search').forEach(function(element) {
            element.addEventListener('my-search-button-click', function(event) {
                alert('clicked: ' + event.detail.button + ' - value: ' + event.detail.value);
            });

            element.addEventListener('my-search-input-change', function(event) {
                console.log('inputed: ' + event.detail.value);
            });
        });
    </script>
</body>
</html>

Web Components en Angular

import { Component } from '@angular/core';
import "@marsgotta/my-search/my-search.js";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  title = 'angular-app';
}
<my-search
  value="Hello World"
  label="I'm a label"
  button="I'm a button"
></my-search>

app.component.ts

app.component.html

Web Components en Vue

<template>
  <div class="hello">
    <my-search
      value="Hello World"
      label="I'm a label"
      button="I'm a button"
    ></my-search>
  </div>
</template>

<script>
  import "@marsgotta/my-search/my-search.js";
  export default {
    name: 'HelloWorld',
  }
</script>

Web Components en React

import "./App.css";
import "@marsgotta/my-search/my-search.js";


function App() {
  return (
    <div className="App">
      <my-search
        value="Hello World"
        label="I'm a label"
        button="I'm a button"
      ></my-search>
    </div>
  );
}

export default App;

¿Web Components es compatible con mi framework o librería?

9. Herramientas para su desarrollo

¿Los Webcomponents son tu camino?

Lit y Lit-Element

Hybrids JS

Stencil JS

Polymer JS

Mención Especial

10. Librerías UI basadas en WC

¿Los Webcomponents son tu camino?

Material Design

Vaadin Web Component

Fast Microsoft

Lion ING

Github Element

11. El futuro de los Web Components

¿Los Webcomponents son tu camino?

¿Los Web Components son el futuro de la Web?

Escenarios para su Uso

  • Ideales para librerias UI o sistemas de diseño
  • Con una APP compleja, seguramente necesite  un framework de apoyo.
  • Muchos frameworks van bien con WebComponents

¿Cuando NO elegir Web Components?

  • Si no necesitas generar código visual.
  • Crear una APP sólo con WC necesita desarrolladores con alto conocimiento en Javascript, HTML y CSS.
  • Tiempo limitado de desarrollo.
  • Web Components para una APP creada con algún frameworks basado en componentes.

12. Conclusión y ¿Ahora qué?

¿Los Webcomponents son tu camino?

Lo que hemos visto

  • HTML, CSS, Javascript y La Web
  • Diversos frameworks Javascript
  • Componentes
  • Arquitectura basada en componentes
  • Frameworks basados en componentes
  • Problematica actual de Frontend
  • Web Components
  • Ventajas de los WebComponents
  • Creación de un WebComponents
  • Uso del WebComponent en diferentes entornos

¿Los Web Components son lo tuyo?

La nueva web con Web Components

  • Webcomponents ha llegado para quedarse
  • Cada vez más empresas que apuestan por ellos
  • Cada vez más proyectos creados solo con Javascript y WebComponents

¿Y ahora qué?

¡Sigue investigando!

Si te interesan los Web Components, esta charla sólo es la punta del iceberg

Hemos terminado :)

¡Muchas Gracias!

13. Sesión de preguntas

¿Los Webcomponents son tu camino?

¡Es hora de las preguntas!

¿Los Web Components son tu camino?

By Mars Gotta

¿Los Web Components son tu camino?

Diapositivas de la charla

  • 106