Crear WebComponents con StencilJS y reutilizarlos en diferentes proyectos
Tags: webcomponents, stenciljs, react, vue
Published: 2021-02-15 10:40:40

Me ha pasado en varias ocasiones la necesidad de re-utilizar un componente en varios proyectos. ¿La solución? Copiar-pegar el componente y llevármelo al proyecto que lo necesite, y tal vez, ajustar alguna cosa para que funcione. ¿Te suena?

> Artículo original: [Crear WebComponents con StencilJS y reutilizarlos en diferentes proyectos](https://alextomas.com/blog/crear-webcomponents-con-stenciljs)

Tal vez esto te funciona cuando el componente en cuestión, por ejemplo un botón, te lo llevas de un proyecto React a otro proyecto React, pero... ¿qué haces si un proyecto es de React, otro de Angular u otro de Vue? Tocaría re-hacer ese botón para cada proyecto. Es decir, estarás haciendo tres veces la misma funcionalidad. No suena bien, ¿no? 💩

Bueno, si te sientes identificado/a con ésta situación, me alegro de no ser el único.

¿Qué tal te suena si hacemos ese mismo botón una sóla vez y lo aprovechamos para nuestros proyectos? Venga, vamos a ello.

## Índice de contenidos

-   Introducción
-   ¿Qué es StencilJS?
-   Crear un proyecto con StencilJS
-   Creación de un componente botón reusable con StencilJS
-   Añadir estilos CSS a un webcomponent
-   ¿Cómo ver un webcompoent creado con Stencil?
-   Generando la distribución
-   Distribuir nuestro webcomponent en un package de Github
-   Integración en un proyecto con React
-   Integración en un proyecto con Vue
-   Conclusiones

### Introducción

En este artículo vamos a ver con un ejemplo práctico cómo implementar un componente con StencilJS (el botón comentado anteriormente), lo publicaremos como un `package` en Github y luego lo integraremos en nuestras aplicaciones, haremos una prueba de integración en Vue y otro en React. ¿Suena bien? ¡Al lío!

### ¿Qué es StencilJS?

[StencilJS](https://stenciljs.com/) es una herramienta de los creadores de [Ionic](https://ionicframework.com/), que definen como «El generador mágico de web components reusables». Es decir, StencilJS permite crear de forma sencilla y sin grandes esfuerzos web components nativos.

### Crear un proyecto con StencilJS

Lo primero que haremos, como es obvio, crear el proyecto, muy fácil:

```bash
npm init stencil
```

Lo que automáticamente nos preguntará que tipo de proyecto es:

![Tipo de proyecto Stencil](https://alextomas.com/blog/webcomponents-stenciljs/tipo_de_proyecto.jpg)

Nos salen tres opciones de tipos de proyecto. Vamos a seleccionar la opción `component` ya que lo que queremos crear es una colección de componentes. Como nombre del proyecto pondremos `custom-components-stencil` (por ejemplo):

![Confirmación de la instalación del proyecto con Stencil](https://alextomas.com/blog/webcomponents-stenciljs/confirmacion_inicio_proyecto_stencil.jpg)

Perfecto, ya hemos creado nuestro primer proyecto con Stencil 🚀, ahora abrimos el proyecto con nuestro IDE favorito y empezamos:

```bash
cd custom-components-stencil
npm install
npm start
```

![Instalación de dependencias y ejecutamos el proyecto](https://alextomas.com/blog/webcomponents-stenciljs/instalar_dependencias_stencil.jpg)

Bien, una vez arrancado el proyecto nos dirá la URL en la que está funcionando nuestro ejemplo, en mi caso en `http://localhost:3333/` donde veremos un ejemplo básico que nos ofrece por defecto StencilJS.

### Creación de un componente botón reusable con StencilJS

Llegados a este punto tenemos ya instalado nuestro primer proyecto StencilJS. Ahora vamos a crear nuestro primer webcomponent de tipo botón reusable.

Lo primero, nos fijaremos en el archivo `src/index.html` donde veremos que Stencil ya nos ofrece un ejemplo de uso de un componente llamado `my-component`, pégale un vistazo a la carpeta `src/components/my-component` que es donde está definido. Básicamente es un div que recibe tres props (first, middle, last) y los pinta por pantalla.

Bien, vamos a crear nuestro componente. Seguiremos los siguientes pasos:

1. Creamos a carpeta dentro de `src` que llamaremos `at-button` (at es de Alex Tomás 😜)
2. Dentro de `src/components/at-button` creamos un archivo con **formato .tsx** que llamaremos `at-button.tsx` ya añadimos lo siguiente:

```javascript
import { Component, Prop, h } from '@stencil/core';

@Component({
	tag: 'at-button',
	styleUrl: 'at-button.css',
	shadow: true,
})
export class ATButton {
	@Prop() text: string;

	render() {
		return <button class='button'>{this.text}</button>;
	}
}
```

Bueno, bueno, esto son muchas cosas, pero que no cunda el pánico. Veamos cuales son las partes del componente:

-   Decorador `@Component` es donde especificamos el nombre del componente y su fichero de estilos.
-   La `@Prop` _text_ va a ser la propiedad que le enviaremos al componente. Estas propiedades por defecto son inmutables desde dentro del componente. Para hacerlas mutables hay que anotarlas con `@Prop({ mutable: true })`, pero no va a ser el caso.
-   El método `render`, que devuelve la descripción necesaria para pintar el componente. Cómo verás usamos **sintaxis JSX**. Si no conoces JSX pásate por este enlace de la documentación de React que explica [qué es JSX](https://es.reactjs.org/docs/introducing-jsx.html).

> Recuerda crear el fichero de estilos en `src/components/at-button/at-button.css`

### Añadir estilos CSS a un webcomponent

Muy sencillo. Al añadir en el decorador `@Component` el nombre del archivo CSS, añadimos las clases que queramos. En nuestro caso le hemos añadido la clase `button` a nuestro botón. Por lo tanto, le añadimos un estilo básico (recuerda que estamos aprendiendo la funcionalidad de los webcomponentes, no en la estética 🙃):

```css
.button {
	background-color: teal;
	border-radius: 30px;
	border: none;
	box-shadow: 2px 2px 9px 2px rgba(0, 0, 0, 0.28);
	cursor: pointer;
	padding: 10px 30px;
	color: white;
}
.button:hover {
	background-color: rgb(0, 146, 146);
}
```

Vale, perfecto. ¿En qué punto estamos?

1. Hemos iniciado el proyecto con Stencil.
2. Tenemos un webcomponent creado que se llama `at-button`.
3. Le hemos dado estilos css.

¿Y ahora como lo puedo ver?

### ¿Cómo ver un webcompoent creado con Stencil?

Recuerda, que al principio del artículo, al crear el proyecto teníamos el comando `npm run start` o `npm start` para ver el proyecto en nuestro navegador. Vale, pero antes vamos a editar el fichero `src/index.html` y lo dejaremos de la siguiente manera:

```html
<!DOCTYPE html>
<html dir="ltr" lang="en">
	<head>
		<meta charset="utf-8" />
		<meta
			name="viewport"
			content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0"
		/>
		<title>Stencil Component Starter</title>

		<script
			type="module"
			src="/build/custom-components-stencil.esm.js"
		></script>
		<script nomodule src="/build/custom-components-stencil.js"></script>
	</head>
	<body>
		<at-button text="¡Hola mundo!"></at-button>
	</body>
</html>
```

Si vamos a nuestro localhost que nos indica Stencil al arrancar el proyecto deberíamos ver nuestro botón:

![Webcomponent Hola Mundo](https://alextomas.com/blog/webcomponents-stenciljs/hola_mundo_button_stencil.jpg)

### Generando la distribución

¡Ya tienes tu primer webcomponent creado con StencilJS! ¿Y hora como lo vamos a usar en otros proyectos? Lo primero que tenemos que hacer, es compilar todo:

```bash
npm run build
```

Lo que te debe generar la carpeta `dist` y `loader`. Perfecto, vamos a crear nuestro `package`en Github.

### Distribuir nuestro webcomponent en un package de Github

Lo primero que necesitaremos será tener creado un repositorio, si no lo tienes creado, hazlo (no voy a detenerme en como crear un repo y en subir los cambios en él ya que no es el objeto de este artículo 😌).

En mi caso el proyecto estará público en la siguiente URL: https://github.com/alextomas80/stencil-webcomponents

Perfecto. Ya tengo mi proyecto compilado y subido a Github. Ahora vamos a crear nuestro package.

### Generar token en Github para crear un package

Aquí vien un poco de magia. Lo primero que necesitamos es un archivo llamado `.npmrc` donde añadiremos lo siguiente:

```
//npm.pkg.github.com/:_authToken=TU_TOKEN
registry=https://npm.pkg.github.com/USUARIO
```

En mi caso será:

```
//npm.pkg.github.com/:_authToken=d7a031caf35....🤫
registry=https://npm.pkg.github.com/alextomas80
```

Para crear un token para publicar un package en tu repositorio necesitarás acceder en Github a Settings > Developer settings > Personal access tokens

![Crear un token personal en Github](https://alextomas.com/blog/webcomponents-stenciljs/crear_token_personal_github.jpg)

Y necesitaremos hacer un cambio en nuestro `package.json`:

```json
{
	"name": "custom-components-stencil"
}
```

Lo cambiaremos por nuestro usuario y nombre que le hayas puesto a tu repositorio, en mi caso quedaría de la siguiente forma:

```json
{
	"name": "@alextomas80/stencil-webcomponents"
}
```

Bien, tenemos todo listo, ahora sí, para enviar nuestro package a Github 🤞🏻

```bash
npm publish --access public
```

Y deberíamos de obtener una respuesta similar a ésta:

![Package subido a Github](https://alextomas.com/blog/webcomponents-stenciljs/subir_package_github.jpg)

¡Sí! ¡Ahora sí! Tienes tu package creado con éxito. ¿Cómo comprobarlo? Accede a la URL de tu repositorio terminado en `packages`: https://github.com/alextomas80/stencil-webcomponents/packages

![Package subido a Github](https://alextomas.com/blog/webcomponents-stenciljs/listado_de_packages_github.jpg)

### Integración en un proyecto con React

Es hora de ver que todo esto ha servido para algo y funciona. Vamos a utilizar nuestro webcomponent `at-button` en un proyecto que vamos a crear con react de una forma rápida. No me voy a entretener mucho con esto:

Creamos nuestro proyecto de ejemplo:

```bash
npx create-react-app test-with-react
```

Arrancamos el proyecto y veremos la pantalla de bienvenida típica de React:

```bash
npm run start
```

![Pantalla inicio de React](https://alextomas.com/blog/webcomponents-stenciljs/bienvenido_react.jpg)

Ahora instalemos nuestro package con nuestro webcomponent. Si volvemos a Github y consultamos nuestro package veremos que nos indica como podemos instalarlo.

![Package subido a Github](https://alextomas.com/blog/webcomponents-stenciljs/instalar_package.jpg)

Así que usaremos NPM para ello:

```bash
npm install @alextomas80/stencil-webcomponents@0.0.1
```

Bien. Ahora vamos a usarlo. Para ello vamos a pegar un vistazo a la [documentación de Stencil para la integración con React](https://stenciljs.com/docs/react), es muy sencillo, yo te lo resumo:

Abrimos el archivo `src/index.js` y lo dejamos de la siguiente manera:

```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

// Importamos nuestro package que hemos creado en los anteriores pasos
import {
	applyPolyfills,
	defineCustomElements,
} from '@alextomas80/stencil-webcomponents/loader';

ReactDOM.render(<App />, document.getElementById('root'));

applyPolyfills().then(() => {
	defineCustomElements();
});
```

Y ahora sí, por fin, vamos a usar y ver nuestro at-button. Abrímos el archivo `src/App.js` y añadimos nuestro botón de la siguiente manera:

```html
<at-button text="Mi WebComponent en React" />
```

Con lo que veremos, por fín, nuestro botón de la siguiente manera y estilo:

![Usando webcomponent personalizado en React](https://alextomas.com/blog/webcomponents-stenciljs/webcomponent_en_react.jpg)

¡Bien! Como verás tiene el mismo estilo que le dimos al componente cuando lo creamos con Stencil. Y además le podemos pasar la propiedad `text` para definir el texto que tendrá el botón. Una maravilla. Pero... ¿no habíamos dicho que el fin de este artículo es el de crear un componente y usarlo en React y Vue?

### Integración en un proyecto con Vue

Creamos nuestro proyecto de ejemplo Vue:

```bash
vue create test-with-vue
```

Seleccionamos las opciones que nos pide (versión de Vue, etc etc, no me voy a entretener en esta parte). Arrancamos el proyecto y veremos la pantalla de bienvenida típica de Vue:

```bash
npm run serve
```

![Bienvenido a VUe](https://alextomas.com/blog/webcomponents-stenciljs/bienvenido_vue.jpg)

Y vamos a hacer exactamente lo mismo que con ejemplo de React. Vamos a instalar nuestro package con NPM:

```bash
npm install @alextomas80/stencil-webcomponents@0.0.1
```

Vamos a pegar un vistazo de nuevo a la [documentación de Stencil para la integración con Vue](https://stenciljs.com/docs/vue), también es muy fácil y muy similar a React:

Abrimos el archivo `src/main.js` y lo dejamos de la siguiente manera:

```javascript
import { createApp } from 'vue';
import App from './App.vue';

// Importamos nuestro package que hemos creado en los anteriores pasos
import {
	applyPolyfills,
	defineCustomElements,
} from '@alextomas80/stencil-webcomponents/loader';

applyPolyfills().then(() => {
	defineCustomElements();
});

createApp(App).mount('#app');
```

Y ya podemos usarlo. Para ello vamos al archivo del ejemplo `src/App.vue` y añadimos:

```html
<at-button text="Mi WebComponent en Vue" />
```

![Usando webcomponent personalizado en Vue](https://alextomas.com/blog/webcomponents-stenciljs/webcomponent_en_vue.jpg)

¡Y ahí tenemos de nuevo exactamente el mismo botón!

![WebComponents - Pura magia](https://alextomas.com/gifs/magic.gif)

## Conclusiones

Con este sencillo ejemplo has podido ver y probar el potencial que nos ofrece Stencil y las posibilidades que nos brinda. Podemos crear componentes rápidamente y completamente reutilizables en cualquier tipo de aplicación ya sea de una u otra tecnología, o incluso sin que tengan uns framework JavaScript por detrás como hemos hecho.

Así pues, si lo que quieres es tener tu libraría de componentes, compartirla con diferentes proyectos y además trabajar en ellos diferentes compañeros de equipo... te recomiendo totalmente su uso.

Y esto es todo. Espero que te pueda servir 😉