🛝 Web Components: cosa sono, a cosa servono e come possono semplificare i tuoi progetti frontend

  

Nello sviluppo frontend moderno, l’esigenza di creare interfacce modulari, riutilizzabili e interoperabili è sempre più forte. In questo contesto, i Web Components si propongono come una soluzione standard, potente e agnostica rispetto ai framework, per affrontare problemi di incapsulamento, duplicazione e manutenzione del codice UI.

In questo articolo vedremo:

  • Cosa sono i Web Components e come funzionano
  • Perché sono utili in scenari reali
  • Un caso d’uso concreto adottato da GitHub
  • Un esempio pratico completo con codice e benefici architetturali
🔗 Ti piace Techelopment? Dai un'occhiata al sito per tutti i dettagli!

🔍 Cosa sono i Web Components?

I Web Components sono una tecnologia nativa dei browser che permette di creare componenti HTML personalizzati, incapsulati e riutilizzabili, senza dipendere da framework esterni.

Sono basati su quattro specifiche fondamentali:

  1. Custom Elements – Definizione di nuovi tag HTML tramite JavaScript (customElements.define()).
  2. Shadow DOM – Incapsulamento dello stile e del markup per evitare conflitti con il resto della pagina.
  3. HTML Templates – Template HTML riutilizzabili che non vengono renderizzati fino all’uso.
  4. ES Modules – Supporto a moduli JavaScript per l’organizzazione e l’importazione del codice.

Esempio base:

class MyButton extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' }).innerHTML = `
      <style>
        button { background: teal; color: white; padding: 10px; border: none; border-radius: 4px; }
      </style>
      <button><slot></slot></button>
    `;
  }
}
customElements.define('my-button', MyButton);

Uso:

<my-button>Clicca qui</my-button>

🎯 Perché usarli: vantaggi e problemi risolti

Problema Soluzione offerta dai Web Components
Conflitti di stile e JavaScript Shadow DOM per isolamento completo
Codice duplicato in progetti multipli Componenti riutilizzabili ovunque
Lock-in su framework Standard web nativi e agnostici
Integrazione difficile in architetture microfrontend Componenti interoperabili

I Web Components sono ideali per:

  • Design system cross-framework
  • Applicazioni legacy
  • Microfrontend e widget distribuiti
  • Sviluppo condiviso tra team diversi

🏢 Caso reale: GitHub e Web Components

GitHub ha adottato Web Components per migliorare la modularità e scalabilità della UI. Esempi reali includono:

  • <relative-time> per mostrare date relative
  • <markdown-toolbar> per l’editor di testo
  • <details-dialog> per finestre modali

Motivazioni:

  • Gestione modulare del codice in un monolite esistente
  • Compatibilità tra team e ambienti diversi
  • Manutenzione semplificata dei componenti

Anche Apple, Adobe e Salesforce usano Web Components per creare design system scalabili e componenti cross-app.


🧪 Esempio pratico: Feedback Widget riutilizzabile

🎯 Requisito

In un’organizzazione con varie app (React, Angular, Vanilla JS), serve un componente uniforme per raccogliere feedback utente:

  • Interfaccia compatta e coerente
  • Invio asincrono a un endpoint
  • Nessun conflitto di stile
  • Facilità di integrazione in tutti gli ambienti

🛠️ Implementazione con Web Component

Struttura file:

feedback-widget/
├── feedback-widget.js
└── index.html

Codice feedback-widget.js:

class FeedbackWidget extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });

    this.shadowRoot.innerHTML = `
      <style>
        * { font-family: sans-serif; }
        .widget { border: 1px solid #ccc; padding: 12px; border-radius: 8px; background: #f9f9f9; width: 250px; }
        textarea, select, button { width: 100%; margin-top: 8px; }
        .success { color: green; display: none; margin-top: 8px; }
      </style>
      <div class="widget">
        <label for="rating">Valutazione:</label>
        <select id="rating">
          <option value="">--</option>
          <option value="1">1 - Pessimo</option>
          <option value="5">5 - Ottimo</option>
        </select>
        <textarea id="comment" placeholder="Scrivi un commento..."></textarea>
        <button id="submit">Invia Feedback</button>
        <div class="success">Grazie per il feedback!</div>
      </div>
    `;
  }

  connectedCallback() {
    const rating = this.shadowRoot.getElementById('rating');
    const comment = this.shadowRoot.getElementById('comment');
    const button = this.shadowRoot.getElementById('submit');
    const success = this.shadowRoot.querySelector('.success');

    button.addEventListener('click', async () => {
      const payload = {
        rating: rating.value,
        comment: comment.value,
      };

      await fetch('https://example.com/api/feedback', {
        method: 'POST',
        body: JSON.stringify(payload),
        headers: { 'Content-Type': 'application/json' },
      });

      success.style.display = 'block';
      button.disabled = true;
    });
  }
}
customElements.define('feedback-widget', FeedbackWidget);

HTML demo index.html:

<!DOCTYPE html>
<html lang="it">
<head>
  <script type="module" src="./feedback-widget.js"></script>
</head>
<body>
  <h2>Feedback Portale</h2>
  <feedback-widget></feedback-widget>
</body>
</html>

✅ Vantaggi ottenuti

Obiettivo Risultato con Web Component
UI standard in tutte le app ✅ Stile e struttura centralizzati
Integrazione facile ✅ Tag HTML nativo
Incapsulamento logica/stile ✅ Shadow DOM
Nessuna dipendenza da framework ✅ Funziona ovunque
Manutenzione e versioning ✅ Distribuibile via CDN/NPM

📈 Estensioni possibili

  • Tema dinamico: <feedback-widget theme="dark">

  • Eventi custom: this.dispatchEvent(new CustomEvent('submitted'))

  • Configurabilità via attributi (endpoint, lang)

  • Test: unitari con Jest, e2e con Playwright

  • Distribuzione: via CDN (Skypack, jsDelivr) o npm


📒 NOTA: Cos'è connectedCallback()?

È un metodo del ciclo di vita che viene chiamato automaticamente dal browser quando un Web Component viene inserito nel DOM (documento HTML).

📌 A cosa serve?

Serve per eseguire codice di inizializzazione, come:

  • aggiungere event listener,
  • fare fetch di dati,
  • aggiornare l’interfaccia,
  • inizializzare logica che richiede che il componente sia effettivamente "attivo" nella pagina.

📘 Sintassi base

class MyElement extends HTMLElement {
  connectedCallback() {
    console.log('Il componente è stato aggiunto al DOM!');
  }
}
customElements.define('my-element', MyElement);

🔁 Quando viene chiamato?

  • ✅ Appena il componente è inserito nel DOM, anche se dinamicamente
  • ❌ Non viene chiamato finché l’elemento è creato in JS ma non ancora aggiunto al DOM

🧠 Esempio pratico

class HelloWorld extends HTMLElement {
  connectedCallback() {
    this.innerHTML = `<p>Ciao dal Web Component!</p>`;
  }
}
customElements.define('hello-world', HelloWorld);

Nel DOM:

<hello-world></hello-world>

🔁 Quando il browser "vede" <hello-world>, invoca connectedCallback() e sostituisce il contenuto con quello definito.

🧹 Nota: ci sono anche altri metodi utili

Metodo Quando viene chiamato
connectedCallback() Quando l’elemento entra nel DOM
disconnectedCallback() Quando viene rimosso dal DOM
attributeChangedCallback() Quando cambiano attributi osservati
adoptedCallback() Quando viene spostato tra documenti (es. iframe)

🧩 Conclusioni

I Web Components rappresentano un’alternativa robusta, standard e interoperabile per costruire UI moderne. Offrono:

  • Isolamento perfetto di stile e logica
  • Riutilizzo tra framework e app
  • Semplicità d’integrazione in microfrontend o portali legacy
  • Manutenzione e test centralizzati

Se il tuo team lavora in ambienti misti o su progetti enterprise, i Web Components possono fare la differenza tra un design system fragile e uno scalabile, solido e moderno.



Follow me #techelopment

Official site: www.techelopment.it
facebook: Techelopment
instagram: @techelopment
X: techelopment
Bluesky: @techelopment
telegram: @techelopment_channel
whatsapp: Techelopment
youtube: @techelopment