Seguimos con la segunda parte de la serie de posts sobre Stencil.js. Partiendo del post anterior, continuamos explicando la creación y distribución de los componentes.
8. Añadiendo atributos al componente
Ahora mismo tenemos un componente estático, es decir, los datos están puestos directamente en el código, con lo cual, no nos serviría de mucho, más allá de tener una bonita tarjeta de presentación para una sola persona.
Así que, en este caso, vamos a añadirle tres parámetros de entrada al componente, para que reciba la imagen, el nombre y el cargo de la persona. Esto se hace con el decorador @Prop (propiedades/atributos). Este decorador indica las propiedades públicas que puede recibir el componente por parte del usuario.
Para ello, realizamos la importación y declaramos los atributos que va a necesitar el componente:
Por último, sustituimos los datos escritos a fuego por esos atributos:
Cuando ya lo tengamos todo codificado, solo nos quedaría llamar al componente pasando los datos como atributos:
9. Entendiendo los @Decoradores
Como hemos dicho anteriormente, los decoradores son construcciones para recolectar todos los metadatos del componente, como las propiedades, atributos y métodos. Una vez que se han recopilado todos los metadatos, los decoradores se eliminan del output, por lo que no incurren en el tiempo de ejecución. Los @Decoradores son:
- @Component() declara un nuevo componente web.
- @Prop() declara una propiedad/atributo. Estos atributos pueden ser: number, string, boolean, array o un objeto.
- @State() declara el estado interno del componente. Cualquier cambio interno al estado hará que se renderice de nuevo el componente.
- @Watch() declara un hook que se ejecuta cuando una propiedad o estado cambia.
- @Element() declara una referencia al elemento.
- @Method() declara y expone un método público.
- @Event() declara un evento del DOM.
- @Listen() listener de los eventos del DOM.
10. Entendiendo el ciclo de vida (Lifecycle hooks)
Existen varios métodos que se invocan durante el ciclo de vida del componente. Estos métodos se le pueden añadir para usarlos en el momento adecuado.
- connectedCallback(). Se ejecuta cada vez que el componente se inserta en el DOM.
- disconnectedCallback(). Se ejecuta cada vez que el componente sale del DOM.
- componentWillLoad(). Se ejecuta justo después de que el componente se inserta en el DOM por primera vez y antes del renderizado. Se ejecuta una sola vez.
- componentDidLoad(). Se ejecuta justo después de la carga y renderización del componente.
- componentWillRender(). Se ejecuta antes de cada renderización.
- componentDidRender(). Se ejecuta después de cada renderización.
- componentWillUpdate(). Se ejecuta cuando el componente se va a actualizar al producirse un cambio en una propiedad o estado. Nunca se llama en el primer renderizado.
- componentDidUpdate(). Se invoca justo después de la actualización del componente. Nunca se llama en el primer renderizado.
- render()
Algunos métodos del LifeCycle devuelven "promises" como:
- componentWillLoad()
- componentWillRender()
- componentWillUpdate()
Hay que tener en cuenta que el ciclo de vida tiene herencia, es decir, si el componente A, tiene dentro un componente B, el componente A no se considera cargado hasta que el componente B termine su carga.
Ejemplo:
Lifecycle hook workflow:
Fuente Imágen: https://stenciljs.com/docs/component-lifecycle
Hagamos un ejemplo con las propiedades y el ciclo de vida. Añadimos a la tarjeta un botón de votación y le damos estilos para que quede de la siguiente manera:
A continuación, añadiremos a nuestro componente una nueva propiedad llamada score y la inicializaremos a 0, la cual, al pulsar el nuevo botón, se irá auto-incrementando, disparando así el método componentWillUpdate(). A este método le programaremos un mensaje de salida en consola, para verificar que se ha ejecutado.
Mostramos el código:
Esto hará que cada vez que pulsemos el botón, se incremente la puntuación, cambiando así el estado de componente y lanzando nuevamente el método componentWillUpdate():
11. Creando la distribución de los componentes
Para ello solo tenemos que ejecutar en consola:
npm run build
Creándose la carpeta "dist" necesaria para la publicación de nuestro proyecto.
Esta carpeta contendrá a su vez 3 sub-carpetas y la librería con la colección de nuestros componentes.
- La carpeta "collection", necesaria para construir una aplicación completa con Stencil.
- La carpeta "my-web-componentes", (en nuestro caso "stencil-demo"), que contendrá toda la lógica de los Web Components.
- La carpeta "types", que recoge todas las definiciones generadas con TypeScript. Útil cuando queremos usar lso componentes en un entorno con TypeScript.
12. Usando los componentes con NPM
Lo primero que habría que hacer es publicarlos en NPM. Deberíamos modificar nuestro archivo package.json para establecer los datos correctamente, como el nombre del componente, su descripción, etc. Además deberíamos redactar correctamente el archivo readme.md, para que los desarrolladores que vayan a consumir nuestros compoenntes comprendan cómo usarlo.
Ahora ejecutaremos:
npm publish
Si es la primera vez que publicamos en NPM tendremos que crearnos un usuario. Enlazo a la web oficial. "Cómo crear un usuario en NPM"
La manera más rápida es tecleando:
npm adduser
Donde se os pedirá un usurio, contraseña y email (que será público) y donde se os enviará un email de verificación que deberemos confirmar para poder usar la cuenta.
A continuación, ya podríamos ejecutar:
npm publish
Y ya tendríamos nuestro componente publicado.
Una vez lo hayamos hecho, tenemos varias formas de incorporar los componentes al nuevo proyecto:
Añadiendo al nuevo proyecto un script similar a:
<script src='https://unpkg.com/my-name@0.0.1/dist/myname.js'></script>
En nuestro caso:
<script src='https://unpkg.com/emlf-card-component@0.0.1/dist/stencil-demo.js'></script>
Con NPM:
npm install my-name --save
Y añadiremos el siguiente script:
<script src='node_modules/my-name/dist/myname.js'></script>
13. Usando los componentes en aplicaciones sin publicarlos en NPM
Un caso particular es si queremos usar nuestros componentes en aplicaciones construidas y desarrolladas sin "frameworks", es decir, creadas solamente con vanilla JS y que además, no tengamos los componentes publicados en NPM. Para ello, solamente debemos incorporar, en el proyecto que queremos usar los componentes, la carpeta build/ y añadir los siguientes scripts:
Y ya usar el componente como un "tag" más de HTML:
Quedando nuestra página index.html de prueba de la siguiente manera:
Para que funcione necesitamos correr la web en un servidor, en mi caso, tengo instalado el plugin "Live Server" de Visual Studio Code, y con él lanzo la página index.html:
Comprobaremos como todo se ejecuta correctamente:
14. Integrando los componentes en los principales frameworks
Para no extender más el post, os enlazo a la documentación oficial de cómo usar los componentes en los principales frameworks de desarrollo: https://stenciljs.com/docs/overview
Conclusiones
Como habrás podido ver, Stencil es un "framework" de desarrollo de componentes con bastante potencial. Entre sus ventajas cabe destacar el uso de TypeScript y JSX y que se pueden crear "Web Components" nativos e independientes de una manera bastante fácil y liviana. A parte, su comunidad y popularidad va creciendo, lo que hace suponer que tendrá cierta evolución.
Pero también presenta una desventaja con respecto a otros "frameworks", y es que el desarrollo de componentes complejos requiere mucha programación, algo en lo que pierde claramente frente a otros, como por ejemplo Angular Elements. Además, actualmente hay poca documentación y podría darse el caso que el equipo de Ionic no le diera todo el soporte necesario.
¿Cuándo usar StencilJs?
En mi opinión, este "framework" funciona, de una forma excelente, para la creación de "Web Componentes" de complejidad media y que vayan a ser consumidos desde proyectos implementados con distintas arquitecturas. Y lo más importante, es que la elección de StencilJs no es excluyente del uso de otros "frameworks".
Con respecto a la creación de aplicaciones completas con Stencil, sigo viendo mucho más potente y robustos a otros "frameworks", como por ejemplo Angular.
Si te ha gustado, ¡síguenos en Twitter para estar al día de próximos posts!
Enlaces de interés
- Documentación oficial: https://stenciljs.com/
- Stencil Component Starter: https://github.com/ionic-team/stencil-component-starter
- NPM Contributing packages: https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry
- NPM Registry: https://docs.npmjs.com/cli/adduser.html