Crear web components con TypeScript
Durante los últimos meses he estado investigando cómo combinar dos de mis «tecnologías» favoritas de los últimos tiempos: los web components y TypeScript.
Entiendo los web components tal como se describen en su página de MDN
Los Web Components son un conjunto de tecnologías distintas que te permiten crear elementos personalizados reutilizables —con su funcionalidad encapsulada y separada del resto de tu código— y utilizarlos en tus aplicaciones web.
Así que, en mi opinión, no son algo que vaya a sustituir a frameworks como React o Angular, sino una forma de crear piezas de código reutilizables que puedes usar con independencia de tu stack de front-end.
Por otro lado, me enamoré de TypeScript desde que empecé a usarlo. Poder usar el último JavaScript, junto con la seguridad y la prevención de errores que da el tipado, es algo que echo de menos cuando tengo que trabajar en un proyecto que no lo tiene.
Entonces dirás: es fácil, empieza a escribir tus componentes con TypeScript, luego los transpilas y los sirves…
y así fue como empezó mi proyecto…
Pronto quise tener una forma de servir mi componente como un único archivo, pero separando el HTML y el CSS en archivos distintos al desarrollar, o usar lit-html para las plantillas, con recarga en caliente durante el desarrollo y una opción para empaquetarlo todo y servirlo en producción… así que empecé a experimentar con webpack (y más tarde lo cambié por Rollup). También quería poder hacer pruebas, así que acabé usando Karma y Jasmine. Quería tener una galería de componentes, así que integré Storybook. Al final quise subir los componentes resultantes a npm, así que necesité crear un package.json y un README.
Y todo eso es lo que incluye de serie lo que he llamado «wc-base-typescript» (muy original, lo sé :)).
Este proyecto te permite empezar a escribir tus web components con TypeScript en un minuto (según tu conexión a Internet) y tener listas todas las funcionalidades que he descrito.
¿Quieres probarlo o usarlo en tus próximos proyectos de web components? Sigue leyendo o ve directamente al repositorio de wc-base-typescript en GitHub, que es más o menos lo mismo pero con menos palabras.
Y, por supuesto, ¡no te olvides de darle una estrella al proyecto en GitHub si crees que se la merece!
Y si hay algo que creas que se puede hacer de otra forma (o mejor), no dudes en decírmelo en los comentarios o enviarme una PR; la colaboración es más que bienvenida :)
¿Listo? ¡Vamos!
Primeros pasos
Lo primero: es mejor copiar el repositorio y hacer el tuyo propio para tu proyecto. Siempre puedes descargar el código, pero por comodidad recomiendo usar degit o una herramienta similar.
npm install -g degit #In case you don't have it installed
degit tx2z/wc-base-typescript
Una vez que el proyecto esté en tu ordenador, entra en la carpeta e instala todas las dependencias de npm:
npm i
¡Y ya puedes empezar a escribir tus componentes! Te dije que un minuto :)
Todos los componentes que crees se guardarán en src/components.
En el proyecto he creado tres componentes para mostrar las distintas opciones disponibles:
El base-component genera un web component sin dependencias ni librerías.
El lithtml-component genera un web component que usa lit-html como librería de plantillas.
El noshadow-component genera un custom element (no sé si se puede llamar web component) sin usar el shadow DOM y sin dependencias ni librerías.
Para empezar rápido, puedes copiar el contenido de uno de los componentes de ejemplo y cambiar lo que necesites.
También es importante incluir tu custom element en public/index.html para poder probarlo mientras desarrollas. Si lo abres verás que he incluido ahí los tres componentes de ejemplo.
Después, para ejecutar un servidor en modo desarrollo solo tienes que escribir en tu terminal:
npm start
Rollup transpilará y empaquetará tus componentes y recargará la página cada vez que guardes un archivo.
Eso es todo. ¡Nada que configurar ni que hacer aparte de centrarte en tu código!
Pruebas
Quizá quieras añadir pruebas a tus componentes para evitar problemas cuando la base de código empiece a crecer… o, mejor aún, seas un superdesarrollador al que le gusta escribir el código siguiendo el proceso de desarrollo guiado por pruebas (TDD).
Me costó bastante añadir pruebas a mis anteriores proyectos de web components, pero, de nuevo, ahora todo viene preconfigurado y funciona de serie. Karma y Jasmine están incluidos como entorno y framework de pruebas.
Dentro de la carpeta de tu componente incluye un archivo que termine en «spec.ts» y escribe tus pruebas (con TypeScript). Por supuesto, hay algunos ejemplos en los componentes de ejemplo.
Por defecto, los lanzadores para Chrome y Firefox ya están instalados y configurados (tus pruebas se ejecutarán en ambos navegadores), pero puedes instalar y usar cualquier otro karma-launcher si quieres.
Para ejecutar las pruebas usa:
npm test
Karma también tiene recarga en vivo, así que si cambias tus componentes o los archivos de pruebas, las pruebas se volverán a ejecutar.
Usar Storybook como galería de componentes
Opcionalmente puedes usar Storybook para desarrollar, documentar y crear una galería de tus web components. Puedes aprender más sobre Storybook en su sitio de documentación.
Un pequeño aviso: Storybook usa webpack y, al compilar, se usará Rollup… el resultado debería comportarse y verse igual, pero no es exactamente lo mismo.
El proyecto usa Storybook for HTML ya ajustado, así que no hace falta más configuración para usarlo con tus componentes. Se incluyen los siguientes addons de Storybook:
Knobs: permite editar dinámicamente las props de los web components desde la interfaz de Storybook.
Viewport: permite mostrar los web components en distintos tamaños y disposiciones dentro de Storybook. Esto ayuda a construir web components responsive dentro de Storybook.
A11y: ayuda a hacer tus web components más accesibles.
Notes: permite escribir notas o documentación de tus web components.
Es una instalación estándar de Storybook. Puedes añadir otros addons o configuraciones que se ajusten a tus necesidades.
Crear historias
Dentro de los componentes de ejemplo hay dos archivos que usa Storybook.
@component.stories.ts: es el archivo para crear una historia de tu componente. Puedes consultar la documentación de Storybook sobre cómo crear historias empezando por esta guía
README.md: se usa para añadir documentación a tu componente mediante el addon Notes de Storybook.
Storybook usará estos dos archivos para generar las historias y la documentación. Una vez que estén los dos archivos, ejecuta Storybook con:
npm run storybook
De nuevo, en los componentes de ejemplo incluidos puedes encontrar ejemplos de todo esto :)
Para generar una aplicación estática de Storybook lista para desplegar, ejecuta:
npm run storybook-build
Encontrarás las compilaciones de Storybook en la carpeta «dist-storybook».
Si quieres publicar tu Storybook en GitHub Pages, te recomiendo instalar storybook-deployer. Hará todo el trabajo por ti.
Ten en cuenta que Storybook es completamente opcional. Si no lo usas, puedes eliminar (o no crear) los archivos @component.stories.ts. Incluso puedes eliminar todas las referencias a Storybook y webpack en el package.json para quitar Storybook por completo de tu proyecto.
Compilar los componentes
Ya es hora de compilar tus componentes para usarlos en otros sitios. No temas, solo ejecuta:
npm run build
Encontrarás las compilaciones en la carpeta «dist».
Tus componentes se compilarán como un archivo js (como módulo ES), para usarlos como módulos en tu aplicación, y en un dist.js (como iife), para usarlos directamente en los navegadores, con el mismo nombre que le des a la carpeta en src/components.
Todos los módulos incluirán sus respectivos archivos de declaración de TypeScript por si alguien quiere usarlos con TypeScript.
Los polyfills de webcomponents también se incluirán en la carpeta «dist»; puedes usarlos o cargar el código directamente desde un CDN como unpkg: https://unpkg.com/@webcomponents/webcomponentsjs@^2/
Y eso es todo: coge tus componentes y úsalos donde quieras. Basta con copiar y pegar la versión (módulo ES o IIFE) que necesites en tu proyecto y usarla.
…
No, así no funcionan las cosas hoy en día, lo sé. wc-base-typescript también simplifica todo lo que necesitas para…
Publicar un componente en NPM
Quizá hayas visto que en la carpeta de cada componente de ejemplo se incluyen también un README y un «package.json». Rollup copiará estos archivos a la carpeta «dist» y añadirá información importante al package.json.
Es decir, no tienes que preocuparte por las propiedades main, module o type, porque se rellenarán automáticamente, pero sí tienes que aportar el resto de la información en el package.json.
Todo lo que tienes que hacer para publicar tu componente en NPM es entrar en la terminal en la carpeta del componente dentro de «dist» y ejecutar:
npm publish
Por supuesto, antes tienes que tener una cuenta en npm e iniciar sesión en la terminal. Recomiendo leer la guía práctica de la documentación de npm antes de publicar un paquete.
Una vez que tu paquete esté en npm, se podrá instalar y usar como cualquier otro paquete de npm. La versión de módulo ES será la predeterminada.
Para cerrar
Así que con el proyecto wc-base-typescript puedes crear, probar y compilar para producción web components con rapidez, publicarlos y, opcionalmente, crear una galería de componentes para mostrarlos.
Si quieres ver uno de los usos que le doy, echa un vistazo a mi generador de licencias Creative Commons como web component con su galería y su repositorio. Lo creé (todo incluido) en unas 6 horas de trabajo intermitente.
¿Qué te parece? ¿Puede serte útil?
PD: No dudes en decirme si lo usas en alguno de tus proyectos, me encantará saber qué estás creando con él :) PD2: Y, de nuevo, si hay algo que creas que se puede hacer de otra forma (o mejor), no dudes en decírmelo en los comentarios o enviarme una PR :D