Antes de escribir una sola línea de código con Lit conviene entender qué problema viene a resolver. Lit no es un framework que inventa su propio modelo de componentes desde cero, como sí hacen React o Vue: es una capa ligera construida directamente sobre un estándar de la propia plataforma web llamado Web Components. Entender ese estándar primero —qué ofrece y qué le falta— es la mejor forma de entender por qué existe Lit y qué gana un desarrollador al usarlo. Esta lección sienta las bases teóricas del curso y presenta el proyecto que construirás a lo largo de los diez módulos: TaskFlow, una aplicación de gestión de tareas al estilo Kanban.
Contenido
- El problema: componentes de interfaz sin un estándar común
- Web Components: las tres tecnologías que forman el estándar
- Qué le falta a los Web Components "vanilla"
- Qué aporta Lit
- Lit frente a frameworks como React, Vue o Angular (una primera foto)
- El proyecto guía del curso: TaskFlow
- El problema: componentes de interfaz sin un estándar común
Durante años, cada framework de JavaScript ha resuelto el mismo problema —dividir una interfaz en piezas reutilizables, encapsuladas y con estado propio— a su manera. React tiene sus componentes con JSX, Vue tiene sus ficheros .vue, Angular tiene sus componentes con decoradores. Todos ellos son excelentes soluciones, pero comparten un inconveniente: un componente de React no se puede usar directamente dentro de una aplicación Vue sin capas de adaptación, y viceversa. Cada framework define su propio concepto de "componente" y ese concepto no sale de sus fronteras.
Esto plantea varios problemas prácticos:
- Portabilidad: si una empresa construye una librería de componentes de interfaz (botones, tarjetas, formularios) con un framework concreto, los equipos que usan otro framework no pueden reutilizarla sin fricción.
- Longevidad: los frameworks evolucionan y a veces quedan obsoletos. Un componente atado a una versión concreta de un framework puede dejar de funcionar cuando ese framework se abandona.
- Coste de aprendizaje: cada framework impone su propia forma de pensar los componentes, aunque el problema que resuelven sea conceptualmente el mismo en todos los casos.
La pregunta natural es: ¿por qué el propio navegador no ofrece un mecanismo nativo para crear componentes de interfaz reutilizables, sin depender de ningún framework? Esa pregunta es precisamente la que responden los Web Components.
- Web Components: las tres tecnologías que forman el estándar
"Web Components" no es una única API, sino el nombre que reciben tres especificaciones del W3C que, combinadas, permiten crear elementos HTML personalizados con comportamiento propio. Vale la pena conocer cada una por separado antes de ver cómo Lit las usa.
Custom Elements
La especificación de Custom Elements permite definir nuevas etiquetas HTML, con un nombre elegido por el desarrollador (siempre con un guion, como <task-card> o <user-avatar>, para evitar colisiones con las etiquetas nativas del navegador). Una vez definida, esa etiqueta se comporta como cualquier otra: se puede insertar en el HTML, tiene su propio ciclo de vida, y el navegador la reconoce como un elemento real del DOM, no como una simulación.
class SaludoElemento extends HTMLElement {
connectedCallback() {
this.textContent = '¡Hola desde un Custom Element!';
}
}
customElements.define('mi-saludo', SaludoElemento);Con solo estas líneas, <mi-saludo> es ya una etiqueta HTML válida que cualquier navegador moderno entiende, sin necesidad de ningún framework ni compilación previa.
Shadow DOM
El Shadow DOM resuelve el problema del encapsulamiento. Cuando un componente tiene su propio HTML interno y sus propios estilos CSS, es fácil que esos estilos "se escapen" y afecten al resto de la página, o que estilos externos rompan el aspecto del componente. El Shadow DOM crea un árbol del DOM separado ("sombra") colgado de un elemento, con su propio CSS que no sale de sus límites y que tampoco recibe estilos externos por accidente.
class Caja extends HTMLElement {
connectedCallback() {
const raiz = this.attachShadow({ mode: 'open' });
raiz.innerHTML = `
<style>
div { border: 2px solid teal; padding: 8px; }
</style>
<div>Contenido encapsulado</div>
`;
}
}
customElements.define('mi-caja', Caja);El detalle de cómo Lit trabaja con estilos y Shadow DOM se estudia con profundidad en el módulo de estilos; de momento basta con saber que existe y para qué sirve: aislar un componente del resto de la página.
HTML Templates
La etiqueta <template> permite declarar fragmentos de HTML que el navegador analiza pero no renderiza hasta que el código JavaScript decide clonarlos e insertarlos. Es la base sobre la que se han construido históricamente muchas soluciones de plantillas eficientes, porque el contenido de una plantilla se puede clonar muchas veces sin volver a analizarlo.
Estas tres piezas —Custom Elements, Shadow DOM y HTML Templates— son estándares soportados de forma nativa por todos los navegadores modernos. No dependen de ninguna librería.
- Qué le falta a los Web Components "vanilla"
Si el estándar ya resuelve el problema, ¿por qué no basta con usarlo directamente, sin ninguna librería? En la práctica, trabajar con Custom Elements "a pelo" resulta tedioso y propenso a errores, por varias razones:
| Necesidad habitual | Cómo se resuelve con Web Components vanilla |
|---|---|
| Actualizar la interfaz cuando cambia un dato | Hay que localizar manualmente los nodos del DOM afectados y modificarlos a mano (textContent, setAttribute...) |
| Evitar reconstruir todo el HTML en cada cambio | Hay que escribir a mano lógica de comparación y actualización selectiva del DOM |
| Declarar la plantilla de forma legible | Se suele recurrir a concatenar cadenas de HTML, con el riesgo de errores y problemas de seguridad (inyección de HTML) |
| Reaccionar quando cambian varias propiedades a la vez | Hay que programar manualmente la agrupación de actualizaciones para no repintar de más |
| Escribir menos código repetitivo | No existe una capa de conveniencia: cada componente repite patrones similares |
Nada de esto es imposible de resolver a mano, pero implica escribir y mantener mucho código de "fontanería" que no aporta valor de negocio. Cuantos más componentes tiene una aplicación, más se nota este coste.
- Qué aporta Lit
Lit es una biblioteca ligera creada por Google (heredera de un proyecto anterior llamado Polymer) cuyo único objetivo es hacer que escribir Web Components sea agradable, sin ocultar ni sustituir el estándar subyacente. Un componente escrito con Lit es un Custom Element real; Lit no crea un modelo paralelo de componentes, simplemente añade una capa de azúcar sintáctico y optimizaciones sobre la API nativa. Sus aportaciones principales son:
- Plantillas reactivas declarativas: se escribe el HTML del componente usando una función de plantilla etiquetada (
html), en un estilo muy legible, y Lit se encarga de actualizar solo las partes del DOM que realmente cambian. - Menos código repetitivo: declarar propiedades reactivas, reaccionar a sus cambios y volver a renderizar se reduce a unas pocas líneas, frente a la gestión manual que exigiría el DOM nativo.
- Rendimiento: Lit no vuelve a analizar ni reconstruir el HTML completo en cada actualización. Internamente identifica qué expresiones de la plantilla han cambiado y actualiza únicamente esos puntos del DOM, lo que la hace muy eficiente incluso en interfaces con muchas actualizaciones frecuentes.
- Tamaño reducido: Lit pesa unos pocos kilobytes comprimidos, muy por debajo del tamaño típico de un framework de aplicación completo.
- Compatibilidad con el estándar: al generar Custom Elements reales, un componente Lit puede usarse en cualquier página HTML, con cualquier framework, o sin ninguno.
En definitiva, Lit no compite con el estándar de Web Components, lo abraza: toma las partes más incómodas de trabajar con Custom Elements y Shadow DOM directamente y las convierte en una experiencia de desarrollo cómoda y moderna.
- Lit frente a frameworks como React, Vue o Angular (una primera foto)
Es habitual preguntarse cómo encaja Lit frente a los grandes frameworks de aplicación. La respuesta corta es que no son exactamente comparables: React, Vue y Angular son frameworks de aplicación completos, con su propio modelo de componentes, enrutamiento, gestión de estado global y ecosistema; Lit es una biblioteca centrada exclusivamente en crear componentes que son, además, estándares nativos del navegador.
Esto tiene una consecuencia práctica importante: un componente hecho con Lit puede usarse dentro de una aplicación React, Vue o Angular como si fuera una etiqueta HTML más, y también puede usarse en una página sin ningún framework. Un componente de React, en cambio, normalmente solo se puede usar dentro de una aplicación React.
Esta comparación se retomará con mucho más detalle —incluyendo ejemplos concretos de interoperabilidad— en el módulo de integración e interoperabilidad. De momento, basta con quedarse con la idea de que Lit y los grandes frameworks no compiten en el mismo terreno: Lit está pensado para construir componentes reutilizables y estándar; los frameworks de aplicación están pensados para construir aplicaciones completas (y, de hecho, pueden usar componentes de Lit dentro de ellas).
- El proyecto guía del curso: TaskFlow
A lo largo de este curso no se van a ver ejemplos sueltos y desconectados entre sí. En su lugar, todo lo que se explique se aplicará de forma progresiva a un único proyecto: TaskFlow, una aplicación de gestión de tareas al estilo Kanban (columnas de tareas como "Pendiente", "En curso" y "Hecho").
TaskFlow se construirá, módulo a módulo, como un conjunto de Web Components hechos con Lit, entre ellos:
<task-card>: representa una tarjeta individual con la información de una tarea.<task-list>: una columna del tablero que agrupa varias tarjetas.<task-board>: el tablero completo, que organiza varias listas.<task-filter>: un control para filtrar las tareas visibles.<user-avatar>: un pequeño componente reutilizable que muestra el avatar de la persona asignada a una tarea.
Cada módulo del curso irá añadiendo capacidades a estos componentes: primero se crearán de forma estática, después se les dará estado y reactividad, más adelante estilos cuidados, comunicación entre ellos mediante eventos, comportamientos de ciclo de vida, funcionalidades avanzadas de plantillas y, finalmente, en el módulo 10, se integrará todo en una aplicación TaskFlow completa, probada y lista para desplegar.
Errores Comunes y Consejos
- Confundir "Web Components" con "Lit": son cosas distintas. Web Components es el estándar de la plataforma; Lit es una librería que facilita trabajar con ese estándar. Se puede usar Web Components sin Lit, pero no se puede usar Lit sin que el resultado sean Web Components.
- Pensar que Lit es "otro framework más" que compite con React: como se ha visto, su propósito es distinto (crear componentes estándar reutilizables, no aplicaciones completas), aunque en la práctica pueda usarse para construir aplicaciones enteras, como se hará con TaskFlow en este curso.
- Subestimar el valor del estándar: quien ya conoce un framework de aplicación puede sentir la tentación de saltarse esta base teórica. Sin embargo, entender qué partes son "estándar del navegador" y cuáles son "azúcar de Lit" ayudará mucho a depurar problemas y a leer documentación técnica más adelante.
- Esperar sintaxis de Lit en el código de ejemplo de esta lección: los ejemplos de código nativo (
HTMLElement,customElements.define,attachShadow) son intencionadamente "vanilla", sin Lit, para mostrar el estándar puro. La sintaxis propia de Lit empieza en la lección 3 de este mismo módulo.
Ejercicios
- Sin usar ninguna librería, crea en un fichero HTML un Custom Element llamado
<mensaje-bienvenida>que, al insertarse en la página, muestre el texto "Bienvenido a TaskFlow" dentro de un<p>. - Modifica el ejercicio anterior para que el texto se renderice dentro de un Shadow DOM, con un estilo CSS que ponga el color de fondo en un tono claro y quede encapsulado (es decir, que no afecte al resto de la página).
- Escribe, en tus propias palabras y sin mirar la lección, una lista de tres tareas de "fontanería" que tendrías que programar a mano si construyeras
<task-card>con Web Components vanilla, sin ninguna librería como Lit.
Soluciones
<!DOCTYPE html>
<html lang="es">
<body>
<mensaje-bienvenida></mensaje-bienvenida>
<script>
class MensajeBienvenida extends HTMLElement {
connectedCallback() {
const parrafo = document.createElement('p');
parrafo.textContent = 'Bienvenido a TaskFlow';
this.appendChild(parrafo);
}
}
customElements.define('mensaje-bienvenida', MensajeBienvenida);
</script>
</body>
</html><!DOCTYPE html>
<html lang="es">
<body>
<mensaje-bienvenida></mensaje-bienvenida>
<script>
class MensajeBienvenida extends HTMLElement {
connectedCallback() {
const raiz = this.attachShadow({ mode: 'open' });
raiz.innerHTML = `
<style>
p {
background-color: #eef6ff;
padding: 8px;
border-radius: 4px;
}
</style>
<p>Bienvenido a TaskFlow</p>
`;
}
}
customElements.define('mensaje-bienvenida', MensajeBienvenida);
</script>
</body>
</html>Al usar attachShadow, el <style> interno solo afecta al <p> que está dentro de ese mismo árbol Shadow DOM: si la página tuviera otro <p> fuera del componente, no se vería afectado por este estilo, y viceversa.
- Una posible respuesta (las tres tareas más habituales): (a) localizar y actualizar manualmente los nodos del DOM cada vez que cambian los datos de la tarea (título, estado, persona asignada); (b) escribir a mano la lógica para no volver a construir toda la tarjeta desde cero en cada cambio, sino actualizar solo lo necesario; (c) gestionar manualmente el registro del elemento, sus atributos iniciales y la sincronización entre atributos HTML y propiedades JavaScript.
Conclusión
En esta lección has visto que los Web Components son un estándar nativo del navegador formado por tres piezas —Custom Elements, Shadow DOM y HTML Templates— que permiten crear elementos HTML reutilizables y encapsulados sin depender de ningún framework. También has visto que trabajar con ese estándar directamente resulta tedioso, y que ahí es exactamente donde entra Lit: una biblioteca ligera que añade plantillas reactivas, actualizaciones eficientes del DOM y mucha menos repetición de código, sin dejar de producir Custom Elements estándar. Por último, se ha presentado TaskFlow, el proyecto de gestión de tareas que iremos construyendo a lo largo de todo el curso.
En la siguiente lección dejaremos la teoría a un lado y prepararemos el entorno de desarrollo: instalaremos Node.js, crearemos un proyecto con Vite, instalaremos el paquete lit y dejaremos todo listo para escribir el primer componente real en la lección 3.
Curso de Lit
Módulo 1: Introducción a Lit y Web Components
- ¿Qué son los Web Components y por qué Lit?
- Configuración del Entorno de Desarrollo
- Tu Primer Componente Lit
- Anatomía de un Componente Lit
Módulo 2: Plantillas Reactivas y Renderizado
- El Motor de Plantillas de Lit
- Expresiones e Interpolación en Plantillas
- Renderizado Condicional
- Renderizado de Listas
- El Ciclo de Renderizado
Módulo 3: Propiedades y Estado Reactivo
- Propiedades Reactivas
- Estado Interno con @state
- Tipos de Propiedades y Conversores Personalizados
- Atributos vs Propiedades y Reflexión
Módulo 4: Estilos en Componentes Lit
- CSS Encapsulado con Shadow DOM
- Estilos Compartidos entre Componentes
- Variables CSS Personalizadas y Theming
- Slots y Estilizado de Contenido Distribuido
Módulo 5: Eventos y Comunicación entre Componentes
- Manejo de Eventos DOM en Plantillas
- Eventos Personalizados: Comunicación Hijo a Padre
- Comunicación de Padre a Hijo con Propiedades
- Patrones de Comunicación entre Componentes Hermanos
Módulo 6: Ciclo de Vida y Comportamiento Avanzado
- Callbacks del Ciclo de Vida
- Hooks Reactivos: willUpdate, updated y firstUpdated
- Controladores Reactivos
- Mixins y Composición de Comportamiento
Módulo 7: Directivas y Funcionalidades Avanzadas de Plantillas
- Directivas Incorporadas: classMap, styleMap e ifDefined
- Directivas Personalizadas
- Renderizado Asíncrono con until
- Contexto Compartido con @lit/context
Módulo 8: Integración, Interoperabilidad y Despliegue
- Usar Componentes Lit en HTML Plano
- Integrar Lit con React, Vue y Angular
- Renderizado en el Servidor con @lit-labs/ssr
- Empaquetado, Publicación y TypeScript
Módulo 9: Pruebas y Buenas Prácticas
- Pruebas Unitarias con Web Test Runner
- Accesibilidad en Web Components
- Rendimiento y Optimización
- Patrones y Anti-patrones Comunes
