Componentes reutilizables con Stencil JS

Stencil JS sirve para construir componentes en varios frameworks y reusarlos como web components.

stencil-js

A veces nos encontramos con componentes que quisiéramos reutilizar entre proyectos sin tener que depender de un framework concreto. Stencil JS nos ofrece esta posibilidad: nos permite crear componentes web usando una sintaxis similar a la de frameworks como React, pero que se compilan en Web Components nativos, listos para usar en cualquier entorno.

Stencil es una herramienta mantenida por el equipo de Ionic y está pensada para facilitar la creación de componentes encapsulados, rápidos y con soporte para TypeScript, JSX y lazy loading sin la necesidad de cargar librerías pesadas en el navegador.

¿Qué es exactamente Stencil?

Stencil es un compilador. No es un framework en sí mismo. Su objetivo principal es ayudarnos a crear Web Components utilizando una sintaxis familiar para quienes ya hayan trabajado con React. Al final del proceso, lo que obtenemos son componentes estándares del navegador, sin dependencias externas.

Entre sus características más útiles:

  • Soporte completo para JSX y TypeScript
  • Generación automática de polyfills para navegadores antiguos
  • Lazy loading de componentes
  • Binding de props, eventos personalizados y slots
  • Posibilidad de generar bindings para otros frameworks (React, Angular, Vue)

Veamos cómo empezar a usarlo.

Primeros pasos

Podemos crear un nuevo proyecto usando el generador oficial de Stencil:

Terminal
npm init stencil

El asistente nos preguntará si queremos crear un componente o una aplicación. Elegimos “component” si solo queremos crear una librería reutilizable.

Una vez instalado, tendremos una estructura básica con un componente de ejemplo. Supongamos que queremos crear un botón personalizado que emite un evento al pulsarlo.

import { Component, Event, EventEmitter, h } from '@stencil/core';
@Component({
tag: 'mi-boton',
styleUrl: 'mi-boton.css',
shadow: true,
})
export class MiBoton {
@Event() customClick: EventEmitter<void>;
private hadleClick = () => {
this.customClick.emit();
};
render() {
return <button onClick={this.hadleClick}>Púlsame</button>;
}
}

Este componente se comporta como un botón normal, pero con la ventaja de que expone un evento personalizado (customClick) que podemos escuchar desde cualquier HTML:

<mi-boton></mi-boton>
<script>
document.querySelector('mi-boton').addEventListener('clickPersonalizado', () => {
console.log('Botón pulsado');
});
</script>

Integración en proyectos existentes

Una de las ventajas de Stencil es que los componentes compilados se pueden usar directamente en HTML o integrarse en proyectos con frameworks populares. Para React, por ejemplo, basta con generar wrappers:

Terminal
npm run build -- --docs --react

Esto nos genera los bindings necesarios para usar los componentes como si fueran elementos de React, manteniendo tipado y compatibilidad.

Además, como son Web Components, podemos usarlos sin problemas en cualquier proyecto con soporte para ES modules: aplicaciones en Vue, Angular o incluso sin ningún framework.

Buenas prácticas

Cuando trabajamos con Stencil, conviene tener en cuenta algunos puntos:

  • Usar @Prop() para pasar propiedades desde fuera
  • Emplear @State() para estados internos del componente
  • Evitar manipular directamente el DOM, y usar JSX para renderizar dinámicamente
  • Encapsular el estilo con Shadow DOM (opcional pero recomendable)
  • No usar lógica de negocio pesada dentro de los componentes

También es conveniente dividir los componentes en unidades pequeñas y mantener los estilos separados para facilitar el mantenimiento y la reutilización.

Desventajas

Aunque Stencil ofrece un enfoque técnico bien resuelto, no está exento de inconvenientes:

  • La curva de aprendizaje puede ser más lenta si no estamos familiarizados con Web Components o con JSX.
  • El ecosistema es más limitado en comparación con frameworks más consolidados. Hay menos ejemplos, tutoriales o integraciones específicas.
  • Algunas herramientas de testing y desarrollo no están bien adaptadas al modelo de Web Components, lo que obliga a configurar entornos personalizados.
  • El rendimiento inicial puede verse afectado si no configuramos correctamente el lazy loading y los polyfills.
  • La generación de bindings para otros frameworks añade una capa de mantenimiento adicional que puede complicar el flujo de desarrollo continuo.

En general, conviene evaluar si los beneficios de la reutilización de componentes compensan estas limitaciones en cada proyecto concreto.

Conclusión

Stencil JS nos permite crear componentes web reutilizables con una sintaxis conocida y sin depender de un framework específico. Ofrece integración sencilla con otros entornos, una buena base técnica (TS, JSX, Shadow DOM) y un enfoque centrado en estándares. Sin ser la solución para todos los casos, puede resolver muy bien ciertos escenarios donde buscamos compatibilidad, rendimiento y control sobre el código que generamos.