Skip to content

Commit 7d06c4c

Browse files
authored
Create Como-crear-una-librer-a-para-Vue3.md
1 parent 0eec3c9 commit 7d06c4c

1 file changed

Lines changed: 234 additions & 0 deletions

File tree

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
---
2+
title: "Como crear una librería para Vue3"
3+
pubDate: "Thu Mar 21 2024"
4+
image: "https://github.com/CuCodersCommunity/cucoderscommunity.github.io/assets/50055316/06b16b54-012b-4d23-8334-e22b8ab5576a"
5+
username: "carlosjorger"
6+
categories: ["tutorials"]
7+
description: "En este artículo explicare paso a paso como crear un librería para Vue3 usando Vite** y **Typescript."
8+
canonicalUrl: ""
9+
---
10+
11+
# Como crear una librería para Vue3
12+
13+
![vue-cover](https://github.com/CuCodersCommunity/cucoderscommunity.github.io/assets/50055316/06b16b54-012b-4d23-8334-e22b8ab5576a)
14+
15+
Estas interesado en ir un paso más allá de crear un producto; estás frustrado de que el ecosistema de **Vue** no es tan rico como el de **React** en cuanto a librerías, frameworks, etc y quieres contribuir a este. Una buena idea podría ser crear tu propia librería donde podrías reutilizar tus propias componentes, composable o módulos js/ts.
16+
17+
En este presente articulo plasmaré mis experiencia creando la librería de drad and drop [vue-fluid-dnd](https://github.com/carlosjorger/vue-fluid-dnd) para **Vue3** en la que actualmente estoy trabajando desde 0 usando **Vite** y **Typescript**. A diferencia de muchos artículos en internet voy a ir un paso más allá explicando un poco más algunos detalles de la configuración de nuestro proyecto que me hubiera gustado encontrarme cuando era un principiante.
18+
19+
### Creando el proyecto
20+
21+
Para crear el proyecto usando **Vite**, se necesita inicializar un proyecto de **Vite** con el siguiente comando:
22+
23+
```bash
24+
npm create vite@latest
25+
```
26+
27+
Se debe seguir los pasos de la creación eligiendo un nombre (en este caso **`template-vue-component-lib`**) y después seleccionar **Vue** y **Typescript**.
28+
29+
```bash
30+
❯ npm create vite@latest
31+
Need to install the following packages:
32+
create-vite@5.2.1
33+
Ok to proceed? (y) y
34+
√ Project name: ... template-vue-component-lib
35+
√ Select a framework: » Vue
36+
√ Select a variant: » TypeScript
37+
```
38+
39+
Después ir al directorio correspondiente y instalar las dependencias:
40+
41+
```bash
42+
cd template-vue-component-lib
43+
npm install
44+
```
45+
46+
Esta es la estructura del proyecto:
47+
48+
![project-structure](https://github.com/CuCodersCommunity/cucoderscommunity.github.io/assets/50055316/c34920cb-691b-456a-b027-07b11ce75855)
49+
50+
Después se limpia el proyecto removiendo los archivos innecesarios (los archivos `index.html`, `App.vue`, `main.ts`, `stye.css` y las carpetas `public` y `assets`).
51+
52+
## Creando la componente de la librería
53+
54+
A continuación se crea una componente que es la funcionalidad que va a proveer nuestra librería.
55+
Creamos el archivo `MessageText.vue` en la carpeta `/src/components`. Este es el código de nuestra componente, note que se está usando sintaxis `script setup` de **Vue3** con **Typescript**:
56+
57+
```vue
58+
<script setup lang="ts">
59+
defineProps<{ msg: string }>();
60+
</script>
61+
62+
<template>
63+
 
64+
<h1 class="message">{{ msg }}</h1>
65+
</template>
66+
67+
<style scoped>
68+
.message {
69+
  color: #bbb;
70+
  background-color: #222;
71+
}
72+
</style>
73+
```
74+
75+
Después se crea el archivo `index.ts` en el directorio `/src`. Este archivo será el que exporte todas las herramientas que va a proveer nuestra librería, en nuestro caso la componente `MessageText`, pero de ser conveniente podemos exportar funciones, constantes, composables de **Vue**, todo lo que se necesite:
76+
77+
```ts
78+
import MessageText from "./components/MessageText.vue";
79+
80+
export { MessageText };
81+
```
82+
83+
## Configuración
84+
85+
Con el código de nuestra librería listo, a continuación se procede a configurar **Vite**, `package.json` y el `tsconfig.json` de nuestro proyecto.
86+
87+
### Configuración de Vite
88+
89+
Para crear nuestra librería haremos uso del ["Modo librería"](https://vitejs.dev/guide/build.html#library-mode) usando la configuración [`build.lib`](https://vitejs.dev/config/build-options#build-lib) dentro de `defineConfig`. Dentro del código se explica cada sección a través de comentarios:
90+
91+
```ts
92+
import { defineConfig } from "vite";
93+
import vue from "@vitejs/plugin-vue";
94+
import * as path from "path";
95+
import { fileURLToPath } from "url";
96+
97+
// https://vitejs.dev/config/
98+
export default defineConfig({
99+
plugins: [
100+
vue({
101+
script: {
102+
defineModel: true,
103+
},
104+
}),
105+
],
106+
build: {
107+
lib: {
108+
// src/indext.ts es donde se expone el código que se va a usar de le librería
109+
entry: path.resolve(__dirname, "src/index.ts"),
110+
name: "TemplateVueComponentLib",
111+
// el nombre de los archivos de salida cuando se le hace build al proyecto
112+
fileName: "template-vue-component-lib",
113+
},
114+
115+
rollupOptions: {
116+
// asegúrate de externalizar las dependencias que no deben ser empaquetadas
117+
// dentro de tu biblioteca, en este caso es `vue` ya que se hará uso del
118+
// `vue` instalada por la aplicación que hace uso de esta librería.
119+
external: ["vue"],
120+
output: {
121+
globals: {
122+
vue: "Vue",
123+
},
124+
},
125+
},
126+
},
127+
});
128+
```
129+
130+
### Configuración del archivo `tsconfig.json`
131+
132+
A continuación se procede a modificar el archivo `tsconfig.json`, este contiene las opciones requeridas para compilar el código de **Typescript** de nuestro proyecto:
133+
134+
```json
135+
{
136+
"compilerOptions": {
137+
"target": "ES2020",
138+
"useDefineForClassFields": true,
139+
"module": "ESNext",
140+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
141+
"skipLibCheck": true /* Bundler mode */,
142+
143+
"moduleResolution": "Node",
144+
"resolveJsonModule": true,
145+
"isolatedModules": true,
146+
"jsx": "preserve",
147+
"esModuleInterop": true,
148+
"outDir": "dist",
149+
"declaration": true,
150+
/* Linting */
151+
"strict": true,
152+
"noUnusedLocals": true,
153+
"noUnusedParameters": true,
154+
"noFallthroughCasesInSwitch": true
155+
},
156+
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
157+
"exclude": [],
158+
"references": [{ "path": "./tsconfig.node.json" }]
159+
}
160+
```
161+
162+
En breve se va a explicar los apartados más importantes de esta configuración, puede profundizar más en la [documentación oficial](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html):
163+
164+
- **esModuleInterop** : Con este flag activado podemos importar módulos de **CommonJS** cumpliendo con la especificación de los módulos de **ES6** en js transpilado.
165+
- **outDir**: es el directorio en el cual se va a generar el js transpilado, por default se genera dicho js en la carpeta que contiene el código de **Typescript** compilado.
166+
- **declaration**: con `declaration` igual a `true` se genera los archivos `.d.ts` para cada archivo **TypeScript** o **JavaScript** dentro de tu proyecto. Dichos archivos de definición de tipos describen la API externa de tu módulo. Con archivos `.d.ts` permiten que herramientas como **Visual Studio** pueden proporcionar _intellisense_ y tipos precisos para código sin tipificar.
167+
- **include**: Especifica un array de nombres de ficheros o patrones de los ficheros que se van incluir en el programa.
168+
- **exclude**: Especifica un array de nombres de ficheros o patrones de los ficheros que no se van a incluir de los especificados en `include`.
169+
170+
### Configuración del archivo `package.json`
171+
172+
El último archivo a configurar pero no menos importante es el `package.json`. En este se puede encontrar detalles como la versión del proyecto, las dependencias necesarias, las compatibilidades, entre otros datos:
173+
174+
```json
175+
{
176+
"name": "template-vue-component-lib",
177+
"version": "0.0.0",
178+
"type": "module",
179+
"repository": {
180+
"type": "git",
181+
"url": "https://github.com/carlosjorger/template-component-lib.git"
182+
},
183+
"files": ["dist"],
184+
"main": "./dist/template-vue-component-lib.cjs",
185+
"module": "./dist/template-vue-component-lib.js",
186+
"exports": {
187+
".": {
188+
"types": "./dist/index.d.ts",
189+
"import": "./dist/template-vue-component-lib.js",
190+
"require": "./dist/template-vue-component-lib.umd.cjs"
191+
},
192+
"./style.css": "./dist/style.css"
193+
},
194+
"types": "./dist/index.d.ts",
195+
"scripts": {
196+
"dev": "vite",
197+
"build": "vite build && vue-tsc --emitDeclarationOnly",
198+
"preview": "vite preview"
199+
},
200+
"peerDependencies": {
201+
"vue": ">=3.3.0"
202+
},
203+
"devDependencies": {
204+
"@vitejs/plugin-vue": "^5.0.4",
205+
"typescript": "^5.2.2",
206+
"vite": "^5.1.4",
207+
"vue-tsc": "^1.8.27"
208+
}
209+
}
210+
```
211+
212+
A continuación voy a indagar en las propiedades del `package.json` que a efectos de nuestra librería son más importantes, sino no le interesa este apartado mucho más detallado y técnico puede continuar leyendo en la próxima sección:
213+
214+
- **repository**: Aquí se concibe la información del repositorio y el sistema de control de versiones usado.
215+
- **files**: Este campo opcional es un array de patrones de archivo que describe el contenido que se va a incluir cuando tu paquete se instala como una dependencia. En este caso incluimos la carpeta **dist** que incluye todo el contenido compilado.
216+
- **main**: A este campo se le asigna el punto de entrada principal a tu programa, el cual es la raíz de la cual se va importar las funciones, objetos o componentes de `Vue`(como en este caso) que necesite el cliente. Aca sería el `javascript` compilado en formato **CommonJS** `./dist/template-vue-component-lib.cjs`.
217+
- **exports**: Esta propiedad permite declarar qué módulo se debe utilizar al realizar solicitudes de módulos como `import "package"` o `import "package/sub/path"`. Dentro se encuentra los siguientes campos anidados:
218+
- Se define los tipos (`types`) en caso de usar `Typescript`.
219+
- El campo`import` define el recurso que se emite desde una solicitud una sintaxis **ESM** o similar.
220+
- El campo `require` es similar al campo `import` pero en el caso de las solicitudes de una sintaxis de `CommonJs/AMD` o similar.
221+
- **types**: Aca se indica la ubicación del archivo que contiene la definición de los tipos de nuestra librería (los `.d.ts`).
222+
- **build**: Este sería el comando que se corre cuando corremos en la consola `npm build`, en este caso primero corremos corremos `vite build` para desplegar nuestro proyecto en la carpeta **dist** y a continuación con el comando `vue-tsc --emitDeclarationOnly` para crear los archivos `.d.ts`.
223+
- **peerDependencies**: Cuando una dependencia se enumera en un paquete como una `peerDependency`, no se instala automáticamente. En su lugar, el código que incluye el paquete debe ser incluido como su dependencia. `npm` lanzara un mensaje alarma sino encuentra este paquete. En este caso nos es muy útil ya que solo verificamos que el cliente tenga una versión de `vue` ya instalada al usar nuestra librería. Este [articulo](https://flaviocopes.com/npm-peer-dependencies/) lo explica de manera muy amena.
224+
225+
## Publicación de la librería
226+
227+
Para publicar nuestra librería, primero corremos el comando `npm run build` para preparar nuestra librería antes de ser publicada.
228+
Después sino estas registrado en **NPM** puedes hacerlo a través de la terminal con el comando `npm adduser` y finalmente publicarlo a **NPM** ejecutando `npm publish`.
229+
230+
## Conclusiones
231+
232+
Gracias a las potencialidades de **Vite** podemos crear fácilmente una librería enriquecida con el tipado de **Vite**. Además, podemos adaptar el conocimiento adquirido en este artículo para hacer una librería para **Vanilla**, **React**, **Svelte**, etc. Si tiene alguna duda me puede contactar en [X](https://twitter.com/carlosjorgerc)
233+
o en [linkedin](https://www.linkedin.com/in/carlosjorger/).
234+
El repositorio del código mostrado se encuentra aquí <https://github.com/carlosjorger/template-component-lib>.

0 commit comments

Comments
 (0)