Web Components: perché Lit è il framework giusto
I Web Components esistono da oltre dieci anni. Sono uno standard del browser, supportati nativamente da tutti i motori moderni, senza dipendenze esterne. Eppure non li usa quasi nessuno.
Il motivo non è tecnico. È che scriverli a mano è verboso al punto da essere scoraggiante. Poi ho scoperto Lit, e ho cambiato idea.
Il problema con i Web Components nativi
Un Web Component nativo è una classe JavaScript che estende HTMLElement. La API è potente ma cerimoniale:
class MyButton extends HTMLElement {
static observedAttributes = ["label"];
constructor() {
super();
this.attachShadow({ mode: "open" });
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
this.shadowRoot.innerHTML = `
<button>${this.getAttribute("label")}</button>
`;
}
}
customElements.define("my-button", MyButton);
Questo è un bottone. Con una prop. Nessuna reattività reale, nessun sistema di template, nessuna gestione dello stato — tutto da implementare a mano ogni volta.
Nessuno scrive così in produzione. Ed è per questo che i Web Components non hanno preso piede.
Cos’è Lit
Lit è una libreria Google (open source, ~6KB gzipped) che aggiunge esattamente quello che manca ai Web Components nativi: un sistema di template reattivo, gestione delle proprietà, lifecycle hooks chiari.
Non è un framework alternativo — compila su Web Components standard. Quello che produce è un custom element registrabile con customElements.define, usabile in qualsiasi HTML, con qualsiasi framework o senza nessuno.
Lo stesso bottone di prima, in Lit:
import { LitElement, html, css } from "lit";
import { customElement, property } from "lit/decorators.js";
@customElement("my-button")
class MyButton extends LitElement {
@property() label = "";
static styles = css`
button { padding: 0.5rem 1rem; }
`;
render() {
return html`<button>${this.label}</button>`;
}
}
Quando label cambia, Lit aggiorna solo la parte del DOM che dipende da quella proprietà — nessun re-render completo, nessun virtual DOM.
Perché Lit è la scelta giusta
1. Zero dipendenze a runtime
React ha bisogno di React. Vue ha bisogno di Vue. Un componente Lit compilato è un Web Component standard — il browser lo esegue senza nessuna libreria da caricare. Il bundle è quello della tua applicazione, non della tua applicazione più un framework.
Per design system distribuiti, widget da embeddare in siti di terzi, componenti che devono girare ovunque: è un vantaggio strutturale.
2. Funziona con qualsiasi stack
Un componente Lit si usa come un tag HTML qualsiasi:
<!-- In un file HTML statico -->
<my-button label="Invia"></my-button>
<!-- In React -->
<MyButton label="Invia" />
<!-- In Astro -->
<my-button label="Invia" />
<!-- In Vue -->
<my-button label="Invia" />
Questo è il vero vantaggio dei Web Components — e Lit lo rende praticabile. Puoi costruire un design system una volta sola e usarlo in qualsiasi progetto, indipendentemente dal framework che cambia ogni due anni.
3. Shadow DOM: stili incapsulati per davvero
Il Shadow DOM non è solo un dettaglio implementativo — è isolamento reale. Gli stili definiti dentro un componente Lit non escono fuori, e gli stili globali non entrano dentro (a meno che non li lasci passare con CSS custom properties).
static styles = css`
/* Questi stili esistono solo dentro questo componente */
:host {
display: block;
}
button {
background: var(--button-bg, #0070f3);
color: white;
}
`;
Nessun conflitto di classi, nessun BEM, nessun CSS Modules. L’incapsulamento è garantito dalla piattaforma.
4. Reattività granulare senza magia
Lit tiene traccia di quali parti del template usano quale proprietà. Quando una proprietà cambia, aggiorna solo quella porzione del DOM — non ri-renderizza tutto.
@customElement("user-card")
class UserCard extends LitElement {
@property() name = "";
@property() online = false;
render() {
return html`
<div class="card">
<span class="name">${this.name}</span>
<span class="status">${this.online ? "online" : "offline"}</span>
</div>
`;
}
}
Se cambia solo online, Lit aggiorna solo lo span.status. Semplice, prevedibile, senza virtual DOM overhead.
Quando usare Lit
Lit non è la risposta a tutto. Per applicazioni SPA complesse con routing, state management globale e server-side rendering, React o SvelteKit rimangono scelte più mature.
Dove Lit eccelle:
- Design system condivisi tra più stack o team
- Widget da embeddare in contesti eterogenei (CMS, siti terzi)
- Componenti autonomi che devono durare nel tempo senza legarsi a un framework specifico
- Progressive enhancement su siti con HTML esistente
Conclusione
I Web Components non hanno sfondato perché la DX nativa è povera. Lit risolve esattamente quel problema — aggiunge reattività, template expressions, CSS scoping e TypeScript support mantenendo l’output 100% standard.
Non è un compromesso. È Web Components come avrebbero dovuto essere fin dall’inizio.