|
| 1 | +# Vite |
| 2 | + |
| 3 | +[Link al repo](https://github.com/Lemoncode/master-frontend-lemoncode/tree/master/03-bundling/07-vite-lib) |
| 4 | + |
| 5 | +Recuerda abrir codepaster. |
| 6 | + |
| 7 | +## Conceptos |
| 8 | + |
| 9 | +Antes de meternos de lleno en lo que es Vite en modo librería vamos a ver qué es lo que nos ofrece el estándar para poder crear y consumir librerías. Al final son los gestores de paquetes los encargados de descargar, instalar y publicar las librerías en nuestros proyectos. Éstas librerías se pueden configurar de tal manera que puedan ser usadas en el navegador o en Node. Como gestor oficial de paquetes tenemos `npm` pero también tenemos otros gestores de paquetes alternativos como `yarn` y `pnpm`. |
| 10 | + |
| 11 | +Cosas que ofrecía Yarn: |
| 12 | + |
| 13 | +- Era más rápido al instalar paquetes que `npm`. |
| 14 | +- Definió en su día el `yarn.lock`, el fichero "lock" para crear un entorno reproducible asegurándose de instalar siempre las mismas versiones. |
| 15 | +- Tenía una resolución de conflictos más efectia que `npm`. |
| 16 | +- Ejecuta ciertas operaciones en paralelo a diferencia de `npm` |
| 17 | +- Implementó el sistema de workspaces antes que `npm`. |
| 18 | +- Modo offline |
| 19 | +- Comprobación de checksum (integridad) |
| 20 | + |
| 21 | +Cosas que ofrecía `pnpm`: |
| 22 | + |
| 23 | +- Eficiencia en disco a la hora de almacenar dependencias |
| 24 | +- Más rápido que `npm` |
| 25 | + |
| 26 | +## Versionado |
| 27 | + |
| 28 | +Conforme va avanzando el ciclo de vida de la librería y se van introduciendo cambios, ¿cómo gestiono el control de versiones? |
| 29 | + |
| 30 | +Para ello se utiliza el estandar de SEMVER, donde define principalmente tres bloques de números: |
| 31 | + |
| 32 | +- El último es `patch`, y debería de ser aumentado cuando hay pequeños cambios que no afectan a la funcionalidad de la librería, como bugfixes, documentación, |
| 33 | +- El intermedio `minor`, debería de ser aumentado cuando se añaden características |
| 34 | +- El primero `major`, debería de ser aumentado con breaking changes, con cosas que rompen la compatibilidad con versiones anteriores como cambios de la API existentes, cambios en el soporte de los entornos de ejecución.. |
| 35 | + |
| 36 | +Si nosotros como consumidores de librerías lo que más debería de importarnos es el actualizar de "major", ya que es posible que parte de la funcionalidad que estemos usando haya cambiado y tengamos que aplicar cambios en nuestro código para adaptarnos a la nueva API. |
| 37 | + |
| 38 | +Importante: Ninguna librería te asegura que siga firmemente la semántica de SEMVER. Intentan cumplirlos siempre, pero siempre puede haber fallos por parte de los creadores. |
| 39 | + |
| 40 | +- [https://semver.npmjs.com/](https://semver.npmjs.com/) |
| 41 | +- [https://medium.com/javascript-scene/software-versions-are-broken-3d2dc0da0783](https://medium.com/javascript-scene/software-versions-are-broken-3d2dc0da0783) |
| 42 | + |
| 43 | +Probar en semver.npmjs.com |
| 44 | + |
| 45 | +- lodash ^1.0.0 |
| 46 | +- lodash ~1.0.0 |
| 47 | + |
| 48 | +## ¿Dónde recupero cada versión? |
| 49 | + |
| 50 | +Cuando utilizamos queremos instalar una librería, en este caso cuando quiero instalar como en ese ejemplo react `^18.1.0`, el gestor de paquetes se encarga de comunicarse con el repositorio de paquetes de npm y de traerte la mayor versión disponible en base al tag de SEMVER que tengamos definido en nuestro proyecto. |
| 51 | + |
| 52 | +## ¿Instalar librerías en local? |
| 53 | + |
| 54 | +¿Qué ocurre si nosotros estamos desarrollando estas librerías y no las hemos pulbicado? Cómo puedo instalar esa librería en local? ¿Cómo puedo probar que estoy añadiendo los ficheros finales y que se instalan correctamente? |
| 55 | + |
| 56 | +Tenemos varias opciones: |
| 57 | +`npm link`. Es la forma más artesanal porque lo que hace es, mediante un proceso de dos pasos, generar un enlace simbólico crear un enlace simbólico. |
| 58 | + |
| 59 | +Para ello te tienes que ir al directorio del proyecto librería y ejecutar `npm link`. Y con eso lo que conseguimos es como añadir nuestro paquete al listado de paquetes instalados de forma global. Podemos verlo haciendo `npm list -g`. |
| 60 | + |
| 61 | +Luego tendríamos que irnos al proyecto que consume esa librería y ejecutar `npm link nombre-librería` y eso te instala la librería a node_modules como enlace simbólico. |
| 62 | + |
| 63 | +El problema de esta aproximación es que la librería no queda reflejada en la definición de dependencias del proyecto, por lo que si eliminamos node_modules y hacemos `npm install` perderemos dicho enlace, a menos que usamos el `npm link my-lib --save`. Además de instalar de forma global la librería. |
| 64 | + |
| 65 | +File la haríamos de forma manual al segundo paso `npm link <lib> --save` |
| 66 | + |
| 67 | +Los workspaces son muy parecidos a "file" |
| 68 | + |
| 69 | +## package.json |
| 70 | + |
| 71 | +Es importante conocer las propiedades del package.json. La mayoría la conoceis. |
| 72 | + |
| 73 | +- author puede ser un objeto |
| 74 | +- |
| 75 | + |
| 76 | +Esta información es importante porque estos van a ser publicados y visibles en el registry de NPM. Incluir un README.md en formato markdown también se reflejará en la web de NPM. |
| 77 | + |
| 78 | +Ejemplo: [@lemoncode/fonk](https://www.npmjs.com/package/@lemoncode/fonk) |
| 79 | + |
| 80 | +## Entrypoints |
| 81 | + |
| 82 | +Además de los campos que ya hemos visto existen otros campos que definen los puntos de entrada. Algunos son oficiales y otros fueron itroducidos por bundlers para poder trabajar mejor con las librerías. |
| 83 | + |
| 84 | +- main: define el punto de entrada de la librería y defina la ruta al index que expone la funcionalidad principal |
| 85 | +- browser: define el punto de entrada de la librería, en caso de que vaya a ser consumida por un navegador. De esta manera podemos tener un punto de entrada distinto si nuestra librería trabaja de forma diferente en node o en el browser. |
| 86 | +- module: se ha convertido en estandar para los bundlers para indicar los ficheros expuestos en formato ESModules. |
| 87 | +- types: define la ruta a los ficheros de definiciones de tipos. Ideal para librerías en TypeScript. |
| 88 | +- exports: la forma oficial de definir en diferentes formatos de módulos nuestra librería, a diferencia de los anteriormente mencionados que inventaron los bundlers. Te permite definir múltiples puntos de entrada para diferentes módulos. [package entry points](https://nodejs.org/api/packages.html#package-entry-points) |
| 89 | +- type: define de forma oficial si tu módulo está definido como ESM o CommonJS. Con `"type": "module"` los ficheros terminados en `.js` son interpretados como ESModules. NodeJS por defecto interpreta el codigo como CommonJS |
| 90 | + |
| 91 | +En los "exports" pueden haber [condicionalmente](https://nodejs.org/api/packages.html#conditional-exports): |
| 92 | + |
| 93 | +- "node-addons" - Como "node" pero para los addons. |
| 94 | +- "node" - Punto de entrada para NodeJS. El formato puede ser tanto CJS como ESM. |
| 95 | +- "import" - Punto de entrada para ESM |
| 96 | +- "require" - Punto de entrada para CJS |
| 97 | +- "default" - Fallback (CJS/ESM). Debe ser definido el último. |
| 98 | + |
| 99 | +NodeJS añade otros no oficiales en la doc a tener en cuenta: [Community Conditions Definitions](https://nodejs.org/api/packages.html#community-conditions-definitions) |
| 100 | + |
| 101 | +## Demos |
| 102 | + |
| 103 | +- [import from "lib" en navegador](https://github.com/WICG/import-maps#packages-via-trailing-slashes) |
| 104 | + |
| 105 | +## Vite library mode |
| 106 | + |
| 107 | +Vamos a ver las librerías que utilizaremos y los bundlers para crear nosotros nuestras propias librerías. Hemos hablado de Rollup como bundler para librerías tanto de JS como de TS. Para aplicaciones web siempre ha predominado de Rollup. Hemos visto que Vite utiliza Rollup por debajo para las builds de producción y que podemos utilizar la configuración y plugins de Rollup para poder crear librerías y aprovechar su potencia. |
| 108 | + |
| 109 | +## A tener en cuenta |
| 110 | + |
| 111 | +Cuando creamos librerías tenemos que tener en cuenta el target. Si va a estar destinada para el navegador.. o para node o ambos, depende de vuestro proyecto. Ya habéis visto que podemos ir jugando con los puntos de entrada.. o usar los exports configurando los targets para los diferentes sistemas de módulos. |
| 112 | + |
| 113 | +Además tenéis que tener en cuenta las dependencias y las peerDependencies. Las peerDependencies son dependencias que deben ser instaladas en el entorno de ejecución o aplicación para que tu librería puede funcionar. El propósito de las peerDependencies son especificar dependencias que se necesitan pero que no están incluídas en el bundle. A partir de la versión 7 de npm son instaladas automáticamente al hacer un npm install. |
| 114 | + |
| 115 | +Ojo que NPM no auto instala las peerDependencies con paquetes locales (mira el [issue](https://github.com/npm/cli/issues/5108)) |
| 116 | + |
| 117 | +También si creais librerías de componentes teneis que tener en cuenta la API, la flexibilidad a la hora de modificar el comportamiento de cada pieza e incluso los estilos... si van a ser CSS global, CSS in JS, módulos CSS, etc. |
| 118 | + |
| 119 | +Por último tener en cuenta la publicación de la librería. Si queremos que sea de acceso público a todo internet o privado. Para tenerlo privado sabed que tenemos varios proveedores y cada uno con su sistema de precios.. por ejemplo el propio registry de npm permite tener una cuenta y organización de pago.. otros como gitlab y github también ofrecen un registry privado donde publicar nuestros paquetes.. o incluso tenemos mediante software de terceros más artesanal el poder tener nuestro registry privado y gestionado por nosotros, algunos gratuítos como verdaccio o hasta de pago como artifactory. En caso de utilizar repositorios privados tendremos que configurar mediante un fichero `.npmrc` el tema de autentificación con este registry con su login, su token.. |
| 120 | + |
| 121 | +## Demos Vite |
| 122 | + |
| 123 | +[build.lib](https://vitejs.dev/config/build-options.html#build-lib) |
| 124 | + |
| 125 | +Recuerda usar `['es', 'umd']` ya que cubre todos los casos |
| 126 | + |
| 127 | +[tabla-esnext](https://compat-table.github.io/compat-table/es2016plus/) Hay gran soporte para las ultimas cosas |
| 128 | + |
| 129 | +### moduleResolution bundler |
| 130 | + |
| 131 | +Tenemos diferentes sistemas de resolución de módulos |
| 132 | + |
| 133 | +Con `node16` tienes que estar renombrando los ficheros depdiendo de si usas `"type": "module"` o CommonJS y usar extensiones `.cjs` o `.mjs`. Además de que tienes que usar las extensiones porque estamos usando el sistema de módulos nativo, y no permite barrels en ESM. |
| 134 | +Vemos que `node` no soporta `exports` |
| 135 | +El modo `bundler` vemos que tiene todas las características y es más flexibles y está pensado para que tu librería se consuma en una aplicación que utilice un bundler. Nosotros la librería que vamos a crear va a ser usada en una aplicación de react con su bundler. |
0 commit comments