Crear un componente en Svelte y publicarlo en NPM
Introducción
A lo largo de los años me he encontrado en proyectos que tienen diferentes áreas dentro de ese mismo proyecto (web, app, panel de administración…) y se tiene que mantener el aspecto de ciertos componentes en todas las partes de la aplicación.
Un ejemplo sencillo
sería el típico botón con el color corporativo. Resulta que ese botón lo quieres utilizar en diferentes proyectos de ese mismo cliente, y el botón va a ser siempre IGUAL. ¿Qué hacemos?
Pues aquí tenemos tres opciones, a mi modo de ver:
- Crear el botón las X veces que nos haga falta para los diferentes proyectos. *Esto está “bien” pero… ¿y si se cambia, por ejemplo, el borde del botón (border-radius)? Lo tendrías que cambiar en todos los botones que te hayas creado en los diferentes proyectos. Ñeeee, bueno 💩 *
- Si tu proyecto va a usar siempre la misma tecnología, por ejemplo Svelte, podrías crearte un componente, publicarlo en un package de NPM y re-utilizarlo allá donde te haga falta. Es lo que veremos en este artículo 🚀
- Pero… ¿si ese mismo proyecto lo vas a usar con diferentes frameworks? por ejemplo, lo quieres usar en React, Svelte y otro en Vue. ¿Qué hacemos?. La respuesta es webcomponents. Te dejo aquí un artículo que escribí hace unos días para crear webcomponents con StencilJS.
Entonces, ahora vamos a ir a la segunda opción y haremos lo siguiente:
- Nos crearemos un componente botón con Svelte.
- Lo probaremos localmente.
- Lo publicaremos en un package de NPM.
- Lo probaremos de nuevo instalando la dependencia.
¿Qué vamos a necesitar?
- Tener cuenta en NPM.
- Tener Node y NPM instalados en tu equipo.
- Ganas de experimentar 🙃
¿Qué componente haremos?
Posiblemente tengas cientos de paquetes en NPM de botones. La idea no es reinventar la rueda, sino conocer el flujo de la creación de un componente y la publicación del paquete. Más adelante te animo que intentes crearte un componente que te solucione A TÍ algún problema concreto. Eso te ayudará a aprender y entender todos los conceptos.
Para nuestro ejemplo crearé un componente que se llamará <At-Button />
.
Iniciamos el proyecto
Bien, lo primero que necesitaremos es una carpeta vacía para iniciar nuestro ¡pequeño gran proyecto!. Desde la consola, por ejemplo, creamos una carpeta y accedemos a la misma, en mi ejemplo la llamaré svelte-custom-button
:
mkdir svelte-custom-button
cd svelte-custom-button
Ahora iniciamos nuestro package.json
. No es necesario que lo escribas a mano, con el siguiente comando lo hará casi todo por tí:
npm init -y
Esto va a crear un archivo package.json
y nos rellenará la información sobre el paquete, como el nombre, autor, descripción, las dependencias que utiliza, la versión etc…
Tendrás la siguiente respuesta:
$ npm init -y
Wrote to /RUTA_DE_TU_PROYECTO/svelte-custom-button/package.json:
{
"name": "svelte-custom-button",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "alextomas80 <XXXXXXXXXXX@gmail.com>",
"license": "MIT"
}
En mi caso author ya está completo porque estoy logeado en npm con mi usuario
alextomas80
.
Puedes rellenar o modificar los campos como el name
, description
, keywords
, author
y license
conforme consideres.
Nota: En el name he añadido mi usuario de npm, en mi caso
@alextomas80
, añade el tuyo ahí.
El siguiente paso será la instalación de dependencias que usará nuestro paquete.
npm install -D rollup rollup-plugin-node-resolve rollup-plugin-svelte svelte
Nuestro package.json
debe de estar de la siguiente forma (yo he cambiado la descripción y keywords):
{
"name": "@alextomas80/svelte-custom-button",
"version": "1.0.0",
"description": "Ejemplo básico de creación de componente Svelte y paquete en NPM",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"svelte",
"ejemplo"
],
"author": "alextomas80 <XXXXXXXXXXX@gmail.com>",
"license": "MIT",
"devDependencies": {
"rollup": "^2.39.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-svelte": "^7.1.0",
"svelte": "^3.32.3"
}
}
Creación del componente
Vamos a necesitar una carpeta que se llamará src
en la raíz del directorio, y dentro un archivo index.js
. En ella contendremos el punto de inicio de nuestro proyecto y el componente de ejemplo.
Nuestro src/index.js
quedará de la siguiente forma:
// src/index.js
import AtButton from './AtButton.svelte';
export default AtButton;
Y como te habrás imaginado, ahora debemos de crear nuestro componente AtButton.svelte
, quedando de momento algo así:
<!-- src/AtButton.svelte -->
<div>Botón de ejemplo</div>
Esto es un fichero de Svelte como seguramente conoces. Puedes importar librerías u otros elementos sin problemas. Así como poner estilos y demás (ahora luego lo veremos).
package.json
Tenemos que hacer unos pequeños cambios al package.json
:
// ...
"main": "dist/index.js",
"module": "dist/index.mjs",
"svelte": "src/index.js",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w"
},
// ...
- En
main
vamos a establecer el output después de correr el script build - En
module
vamos a definir lo mismo pero como salida un archivo .mjs, para que Node distinga entre módulos creados con CommonJS y ES6. - En
svelte
, vamos a definir la ruta de nuestro archivo index.js creado anteriormente. - Y por último definimos los
scripts
como para crear el build o correr en desarrollo.
Nota: la carpeta
dist
que hasbrás visto que apunta enmain
ymodule
se generará automáticamente.
El package.json debería quedar así:
{
"name": "@alextomas80/svelte-custom-button",
"version": "1.0.0",
"description": "Ejemplo básico de creación de componente Svelte y paquete en NPM",
"main": "dist/index.js",
"module": "dist/index.mjs",
"svelte": "src/index.js",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w"
},
"keywords": [
"svelte",
"ejemplo"
],
"author": "alextomas80 <XXXXXXXXXXX@gmail.com>",
"license": "MIT",
"devDependencies": {
"rollup": "^2.39.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-svelte": "^7.1.0",
"svelte": "^3.32.3"
}
}
Creamos el fichero rollup.config.js
Si has trabajado con Svelte en alguna otra ocasión, conocerás este archivo:
import svelte from "rollup-plugin-svelte";
import resolve from "rollup-plugin-node-resolve";const pkg = require("./package.json");export default {
input: "src/AtButton.svelte",
output: [
{ file: pkg.module, format: "es" },
{ file: pkg.main, format: "umd", name: "Name" },
],
plugins: [svelte(), resolve()],
};
¿Cómo puedo probar mi componente localmente?
Antes de publicar el componente en el paquete de NPM, lo suyo sería probarlo para ver como queda y si estamos satisfechos con el resultado. Entonces, vamos a probarlo en un proyecto nuevo de Svelte. Para ello, nos crearemos un nuevo componente de Svelte, yo en mi caso me voy a crear un proyecto llamado svelte-playground
ejecutando el siguiente comando:
npx degit sveltejs/template svelte-playground
Luego accedemos al proyecto e instalamos las dependencias:
cd svelte-playground
npm install
Bien. Ya tenemos lo siguiente:
- Un proyecto (
svelte-custom-button
) con nuestro componente, listo para ser probado. - Un proyecto Svelte (
svelte-playground
) para probar el componente que enviaremos a NPM.
Primero, accedemos al proyecto del componente svelte-custom-button
y ejecutamos:
npm link
Y recibirás una respuesta similar a:
npm WARN svelte-custom-button@1.0.0 No repository field.audited 17 packages in 0.711s3 packages are looking for funding
run `npm fund` for detailsfound 0 vulnerabilities
/usr/local/lib/node_modules/svelte-custom-button -> /RUTA_DE_TU_PROYECTO/svelte-custom-button
Y luego, en el proyecto svelte-playground
ejecutaremos npm link /la-ruta/de/tu-paquete
, en mi caso:
npm link /RUTA_DE_TU_PROYECTO/svelte-custom-button
Con esto podremos probar localmente nuestro paquete. ¡Perfecto! ¡Y en tiempo real!
Usar componente localmente
Accede a tu proyecto svelte-playground
y corre el proyecto con el comando npm run dev
, con lo que verás la pantalla generada por Svelte en http://localhost:5000/:
Y ahora editaremos nuestro fichero src/App.svelte
dejándolo así:
<script>
export let name;
// Importamos nuestro componente Botón
import AtButton from "@alextomas80/svelte-custom-button";
</script><main>
<h1>Hello {name}!</h1>
<p>
Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn
how to build Svelte apps.
</p> <!-- Usamos el componente -->
<AtButton />
</main><style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
} h1 {
color: #ff3e00;
text-transform: uppercase;
font-size: 4em;
font-weight: 100;
} @media (min-width: 640px) {
main {
max-width: none;
}
}
</style>
¡Y entonces tendremos nuestro botón! Quedando así:
Bueno, no es un gran componente, pero por lo menos ya lo vemos.
Editar componente localmente a tiempo real
Vamos a darle estilo a nuestro botón. Volvemos al proyecto svelte-custom-button
y dejaremos nuestro componente de la siguiente manera:
<script>
// Le enviaremos al botón la propiedad `title`, en caso de no recibirla le ponemos valor por defecto
export let title = "Botón";
</script><div class="boton">{title}</div><style>
/* Aplicamos unos pocos estilos al botón */
.boton {
background-color: coral;
border-radius: 3px;
cursor: pointer;
display: inline-block;
padding: 10px 20px;
transition: 0.3s ease;
}
.boton:hover {
background-color: darkorange;
}
</style>
Si accedes de nuevo a http://localhost:5000/ deberías ver los cambios reflejados automáticamente. El botón debería quedarte así:
Y si ahora le pasamos la propiedad title
a nuestro <AtButton />
podemos personalizar el título del mismo:
<AtButton title="Enviar formulario" />
Quedando:
Publicar el paquete en NPM
¡Perfecto! Ya tenemos nuestro componente, nos gusta y ahora lo queremos publicar en un paquete en NPM para usarlo en futuros proyectos. Bien, es muy fácil.
Deberás estar logeado en npm. Si no lo sabes si lo estás ejecuta: npm whoami
(en mi caso me responde alextomas80, que es mi usuario de npm). Doy por hecho que tienes cuenta en NPM! 😂
Si no estás logeado: npm login
Es recomendable haber creado en el directorio raíz el archivo README.md con la información de nuestro paquete. Así otros usuarios podrán conocer la información de uso, propiedades, configuraciones etc etc…
npm publish --access public
Y si todo va bien deberías obtener lo siguiente:
Ahora si tu perfil de npm (https://www.npmjs.com/settings/alextomas80/packages) verás que te aparecerá tu paquete. En el caso de que no lo haga, a veces tarda unos minutos en aparecer, puedes buscarlo directamente en el buscador, en mi caso buscaría @alextomas80/svelte-custom-button
que será el nombre del paquete.
¿Cómo puedo probar mi componente desde NPM?
¡Muy fácil! Esto lo habrás hecho cientos de veces, bueno, igual alguna menos 😌 Accede a la información del paquete, en nuestro ejemplo: https://www.npmjs.com/package/@alextomas80/svelte-custom-button
Ahí nos indica como hacer la instalación a través de NPM:
npm i @alextomas80/svelte-custom-button
Y el uso es igual que el de antes:
<script>
import AtButton from "@alextomas80/svelte-custom-button";
</script><main>
<AtButton title="Acceder al panel" />
</main><style>
main {
text-align: center;
padding: 1em;
max-width: 240px;
margin: 0 auto;
}
</style>
Quedando de nuevo nuestro botón como lo teníamos:
Nota: Si no te sigue refrescando el componente desde el paquete local tendrás que hacer unlink. Accede al directorio del proyecto
svelte-custom-button
y ejecutanpm unlink
y lo mismo en el proyecto Sveltesvelte-playground
ejecutandonpm unlink /RUTA_DE_TU_PROYECTO/svelte-custom-button
. Yo por lo menos tuve que hacerlo porque me seguía refrescando los cambios locales y no veía el componente de NPM 🙈
Repo de ejemplo: https://github.com/alextomas80/svelte-component-package-npm
Y esto es todo. Espero que te pueda servir 😉