Crear y publicar librería en NPM / Modo librería

En este capítulo, os explicaré todas las claves para poder crear nuestra propia librería Qwik, paso a paso, y distribuirla en NPM para que otras personas puedan utilizarla, al igual que nosotros utilizamos librerías externas en nuestros proyectos.

Para trabajar con este capítulo os recomiendo que estudiéis los contenidos de los capítulos anteriores, sobre todo el correspondiente a componentes ya que será lo que vamos a trabajar principalmente junto con los conceptos de desarrollo de una librería en Qwik.

Apartados que vamos a ver en este capítulo

Estos serán los temas que vamos a trabajar en este capítulo, desde lo que es la introducción hasta publicar nuestro primer paquete Qwik en NPM.

Introducción

Qwik utiliza el modo de librería de Vite para crear librerías de componentes.

Modo librería de Vite

Para acceder al modo de librería de Vite a continuación podréis encontrar esa información dentro de la referencia oficial:

https://shorten-up.vercel.app/EQ7twSYrM4

Para crear una librería de componentes para Qwik, debemos asegurarnos de seguir unas reglas específicas para que el optimizador de Qwik pueda reconocer nuestra librería como tal.

La forma más sencilla de crear una nueva librería de componentes es utilizando la referencia oficial, donde se exponen los temas a tener en cuenta y los pasos a seguir, aunque bajo mi punto de vista creo que le falta información y faltaría hacerle algunos ajustes para mejorarla y que sea más cómoda de utilizar.

Documentación Qwik - Crear librerías de componentes

A continuación podéis encontrar la referencia oficial de la documentación de Qwik para poder seguir los pasos y crear vuestra librería de componentes:

https://shorten-up.vercel.app/2qBiEimJpm

Por este motivo, siguiendo un poco mi propia estructura, mis gustos personales y mi forma de organizar las cosas, he creado mi versión alternativa añadiendo algunas configuraciones que me gustan más.

Por supuesto, siempre respetando que el optimizador de Qwik pueda reconocer el proyecto como una librería de Qwik, si no, que sentido tendría hacerlo.

También se respeta lo que se refiere a la estructura de ficheros que se propone en la implementación oficial. Los cambios que he proporcionado son más enfocados a temas de compilación y forma de trabajar con ello.

Requisitos mínimos previos

Preparativos

Para continuar con el desarrollo de la librería paso a paso, tenemos que descargar el proyecto que utilizaremos como plantilla para realizar el desarrollo de la librería.

Os proporciono dos opciones, seleccionar la que más os guste:

Una vez que hayamos descargado el proyecto

Con esto ya tenemos el primer paso completado, el de tener disponible el proyecto.

Lo abrimos en el editor de código (Visual Studio Code) y debemos de tener el proyecto abierto y se tiene que ver esta estructura.

Estructura del proyecto

Ahora que ya disponemos del proyecto y lo tenemos abierto, listo para trabajar, vamos a analizar su estructura mencionando los aspectos que debemos tener en cuenta en lo que respecta al proyecto de la librería.

De esta manera, vamos a conseguir trabajar sabiendo qué estamos modificando y qué necesitamos para llegar hasta el punto de publicar nuestra librería sin hacer las cosas a ciegas, que no suele ser muy buena idea.

Es prácticamente la misma estructura que el proyecto que se creará a partir del generador oficial aunque esta plantilla tiene algunas diferencias que facilitan más el trabajo.

Esta será la estructura:

├── README.md
├── package.json
├── src
│     ├── components
│     │     ├── counter
│     │     │     └── index.tsx
│     │     └── logo
│     │           └── index.tsx
│     ├── hooks
│     │     └── useCounter.tsx
│     ├── entry.dev.tsx
│     ├── entry.ssr.tsx
│     ├── index.ts
│     └── root.tsx
├── tsconfig.json
└── vite.config.ts

De estos archivos los más importantes en una librería en Qwik son los ficheros package.json y vite.config.ts configurados correctamente.

Ahora vemos estos ficheros junto con los otros con sus características y detalles a tener en cuenta.

package.json

Empezamos hablando del fichero package.json, que es el fichero que necesitamos para poder añadir y gestionar la información de nuestros proyectos de desarrollo de software en JavaScript y Node.JS.

Se utiliza principalmente para gestionar las dependencias del proyecto, scripts de ejecución, metadatos y otra información relevante que se necesitará especificar.

En el caso de Qwik, tenemos que tener en cuenta la siguiente estructura, cuyas propiedades que se muestran a continuación son importantes y aunque algunos no sean obligatorios su uso, se recomiendan añadirlos para respetar su optimización a proyectos Qwik.

El contenido del fichero del manifiesto del template que estamos usando para el desarrollo de una librería de Qwik es el siguiente:

{
    "name": "qwik-template-library",
    "version": "0.0.1",
    "description": "Create a reusable Qwik component library",
    "main": "./dist/index.qwik.cjs",
    "qwik": "./dist/index.qwik.mjs",
    "module": "./dist/index.qwik.mjs",
    "types": "./dist/types/index.d.ts",
    "exports": {
    ".": {
        "import": "./dist/index.qwik.mjs",
        "require": "./dist/index.qwik.cjs",
        "types": "./dist/types/index.d.ts"
    }
    },
    "files": [
      "dist",
      "!dist/types/root.d.ts",
      "!dist/types/entry.dev.d.ts",
      "!dist/types/entry.ssr.d.ts"
    ],
    "directories": {
      "lib": "dist"
    },
    "engines": {
      "node": ">=15.0.0"
    },
    "private": false,
    "type": "module",
    "scripts": {
      ...
    },
    "devDependencies": {
      ...
    }
}

Ahora se hará hincapié en las propiedades más importantes y las restantes las menciono en conjunto con una breve explicación.

  • qwik: Una propiedad super importante es la propiedad qwik, que será el punto de entrada para que el Optimizador de Qwik reconozca como una librería de Qwik. Hay que añadir la referencia con la extensión .qwik.mjs, que de lo contrario el optimizador de Qwik NO LO RECONOCERÁ. Este fichero se genera con el script build mediante la ejecución de npm run build

  • main: Punto de entrada de la librería. En este caso añadimos el fichero con la extensión .qwik.cjs que contiene el código compilado de Common JS (Javascript común). Este fichero se genera también con el script build.

  • types: Referencia para acceder a los types de nuestra librería. En este caso añadimos el fichero con la extensión .d.ts que contiene el código compilado con los tipos generado de nuestro desarrollo. También generado con build.

  • name: Nombre del paquete. Fundamental y es obligatorio (en cualquier paquete de NPM que queramos publicar). Debe de respetarse la convención de nombres de paquetes teniendo en cuenta lo siguiente. Luego vemos este detalle cuando nos centremos en el punto de prepararlo para producción.

  • exports: Referencias a los ficheros generados para poder consumir la librería.

  • files: Ficheros que se añadirán al paquete final para publicarlo en NPM tanto haciendo npm pack (para pruebas locales donde agrupa los ficheros compilado generando un fichero tgz) o el comando para mandarlo a producción, es decir, npm publish. Las referencias de los ficheros que contienen ! por delante serán ficheros que se ignorarán al empaquetar la librería. Eso si, hay que tener en cuenta que no se ignoran al hacer npm run build.

  • type: Añadimos module, no cambiar esto ya que estamos definiendo que es un módulo.

Luego tendremos las siguiente propiedades como engines(versión de Node que se usará, en este caso mayor o igual que 15, recomendable hacerlo con 16 o 18), y devDependencies(dependencias que necesitamos para nuestro desarrollo) y scripts(Ejecutar las diferentes tareas como compilación, generación de los types, etc.).

Con esto, ya hemos analizado el fichero del manifiesto de nuestros proyectos, el package.json.

vite.config.ts

En comparación con una configuración normal de Vite, las bibliotecas utilizarán el modo librería de Vite, lo cual nos obliga a que tengamos bien configurado el script build.lib, cosa que ya tenemos completado con esta plantilla, ya que viene testeado correctamente.

Si necesitáis hacer algún cambio, os recomiendo que uséis el enlace proporcionado (al inicio del capítulo) sobre como trabajar en el modo de librería en Vite.

A tener en cuenta

Actualmente no es necesario realizar cambios, ya que está configurado, por lo que si en algún momento hay que hacer algún cambio, se mencionará.

El fichero de configuración en este caso será el siguiente:

import { defineConfig } from 'vite';
import { qwikVite } from '@builder.io/qwik/optimizer';
import dts from 'vite-plugin-dts';

export default defineConfig(() => {
    return {
    // 1.- Opciones de compilado
    build: {
        target: 'es2020',
        // 2.- Configuración para generar nuestra librería compilada con ficheros necsarios para Qwik
        lib: {
        entry: './src/index.ts',
        formats: ['es', 'cjs'],
        fileName: (format: string) => `index.qwik.${format === 'es' ? 'mjs' : 'cjs'}`,
        },
        // 3.- Directorio de salida, fijaros que concuerda con main, qwik,...del package.json
        outDir: './dist'
    },
    plugins: [qwikVite(), dts()],
    };
});

src

Directorio donde se añaden todos los componentes y elementos que van a implementarse en nuestra librería, es decir, donde vamos a alojar todo el código fuente del desarrollo.

Es importante que tengamos el fichero index.ts dentro de el, ya que este fichero es el punto de entrada de nuestra librería, exportando todos los componentes y funciones que deseamos proporcionar a los que consumen la librería para facilitar su uso, simplemente teniendo que hacer referencia al nombre del paquete y NO a nombre del paquete + el path relativo donde se encuentre ese elemento.

La estructura del directorio en este template es la siguiente:

...
├── src
│     ├── components
│     │     ├── counter
│     │     │     └── index.tsx
│     │     └── logo
│     │           └── index.tsx
│     ├── hooks
│     │     └── useCounter.tsx
│     ├── index.ts
...

Ahí podemos ir añadiendo todo lo que necesitemos, pero eso si, procurad ir añadiendo en el fichero index.ts todos los elementos que queramos compartir.

Ahora mismo, con la estructura que tenemos, el fichero src/index.ts tiene configurado de la siguiente forma:

export { Logo, type LogoProps } from './components/logo';
export { Counter } from './components/counter';
export { useCounter } from './hooks/useCounter';

Con esto, si ya tenemos por ejemplo que nuestro paquete se llama qwik-utilities-lib para poder consumirlo en una aplicación que hemos instalado estas dependencias, podremos consumirlo de la siguiente forma:

import {Logo, Counter} from qwik-utilities-lib;

Donde estaremos accediendo a los componentes <Logo /> y <Counter />, pudiendo acceder si quisiéramos al hook useCounter y a los props del componente <Logo />, que será LogoProps.

tsconfig.json

El archivo tsconfig.json es un archivo de configuración que se utiliza en proyectos que están escritos en Typescript.

Nos proporciona opciones y ajustes para el compilador de TypeScript, permitiendo personalizar el comportamiento de compilación y configurar características específicas del proyecto.

Contiene información como la versión de TypeScript utilizada, los archivos fuente a incluir o excluir, la ruta de salida de los archivos compilados y otras configuraciones relacionadas con el proceso de compilación de TypeScript.

src/entry.dev.tsx, src/entry.ssr.tsx y src/root.tsx

Las librerías también son aplicaciones, a menor escala, pero lo son.

El inicio de la librería también será una aplicación independiente de Qwik (sin enrutamiento ni Qwik City) donde podréis encontrar los archivos src/entry.dev.tsx, src/entry.ssr.tsx y src/root.tsx.

No os preocupéis por ellos, no van a formar parte de la librería final, pero son útiles durante el desarrollo y las pruebas, para que podamos probar nuestras implementaciones en una aplicación de Qwik real.

Para ignorar estos ficheros, recordad lo visto en el package.json con lo definido en la propiedad files, cuyo apartado muestra los 3 ficheros que tienen por delante ! haciendo que se ignoren en la librería compilada. Se ha configurado de esa manera para que esos ficheros no formen parte del resultado final, ya que solo nos serán útiles en el desarrollo.

Una vez analizada la estructura principal de la librería, comenzamos ejecutando el comando para iniciar la aplicación real de Qwik donde se pueden ver como se consumen los dos componentes que contiene la librería actualmente.

Probando los elementos de la librería en app Qwik

Para iniciar el proyecto (estamos trabajando en la librería), debemos de ejecutar el siguiente comando:

npm start

Una vez que se compile y esté todo OK, se nos abre una nueva pestaña y debería de aparecer algo similar a lo siguiente:

Y todo esto se ha definido en el fichero src/root.tsx de la siguiente manera:

// 1 Importamos los componentes que estamos usando
import { Counter } from './components/counter';
import { Logo } from './components/logo';

// 2.- Consumimos los componentes Logo y Counter, como se puede ver
export default () => {
  return (
    <>
      <head>
        <meta charSet='utf-8' />
        <title>Qwik Library Template - By Anartz</title>
      </head>
      <body>
        <h2>Example components</h2>
        <h4>Created by: Anartz Mugika Ledo</h4>
        <h4><code>{`<Logo />`}</code> component</h4>
        <Logo
          url='https://qwik.builder.io/'
          alt='Qwik Logo'
          width={400}
          height={147}
          image='https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F667ab6c2283d4c4d878fb9083aacc10f'
        />
        <h4><code>{`<Counter />`}</code> component with <code>{`useCounter`}</code> custom hook</h4>
        <Counter />
      </body>
    </>
  );
};

Cualquier cambio, para añadir nuevos componentes, lo haremos dentro de body.

Creando y consumiendo nuevo componente

Ahora que ya hemos visto como está estructurado el directorio del código fuente de nuestra librería y como consume los componentes que contiene, vamos a crear un componente propio desde 0.

Recordario sobre como trabajar con componentes

Cualquier duda o consulta accedemos a como trabajar con componentes (Capítulo 3) para repasar su contenido de nuevo.

Creamos el directorio hello dentro de src/components y habiéndonos ubicado sobre el, añadimos el fichero index.tsx con el siguiente contenido:

import { component$ } from '@builder.io/qwik';

export const Hello = component$(() => {
  return <>Hola, estamos trabajando con la librerías en Qwik :)</>;
});

Y si lo añadimos en el fichero src/root.tsx:

// ...
// 1.- Importamos
import { Hello } from './components/hello'

// 2.- Añadimos el componente para consumirlo
export default () => {
  return (
    <>
      <head>
        <meta charSet='utf-8' />
        <title>Qwik Library Template - By Anartz</title>
      </head>
      <body>
        ...
        <br/><br/><br/>
        // 2.- Consumimos el componente
        <Hello />
      </body>
    </>
  );
};

Al guardar y recargarse la página inicial de la aplicación, se verá de la siguiente forma:

Con esto podemos decir que ya tenemos lo necesario, aunque no hemos terminado, debemos de hacer que sea visible desde el punto de entrada en src/index.tsx, por lo que vamos a añadirlo con lo siguiente:

export { Hello } from './components/hello';

Siendo el resultado en src/index.tsx:

export { Logo, type LogoProps } from './components/logo';
export { Counter } from './components/counter';
export { useCounter } from './hooks/useCounter';
export { Hello } from './components/hello';

Con esto, ya hemos visto todo lo que es relacionado a consumir dentro del proyecto de la librería y crear un componente de una manera muy sencilla.

Pasamos al punto donde ya vamos a hacer que nuestro desarrollo esté disponible a todo el mundo, pudiendo ser con un paquete que se ejecutará en local o publicándolo en NPM.

Lo vamos a ver de las dos formas, ya que tanto hacerlo para trabajar en local o con NPM me parecen super interesantes.

Compilación

Para publicar nuestra librería, primero debemos compilarla en modo librería

Para hacer este proceso y crear la compilación debemos de ejecutar el script build

npm run build

Se ejecutarán varios scripts de manera consecutiva de manera ordenada

npm run build.types
npm run build.lib
npm run lint

Una vez que se completan los pasos, se consigue el resultado generado en el directorio dist, que con lo que tenemos hasta ahora debería de ser algo así:

...
├── dist
│     ├── types
│     |    │── entry.dev.d.ts
│     |    │── entry.ssr.d.ts
│     |    │── root.d.ts
│     |    │── index.d.ts
│     |    │── components
│     │    │      ├── counter
│     │    │      │     └── index.d.ts
|     |    │      ├── logo
│     │    │      │     └── index.d.ts
|     |    │      └── hello
│     │    │            └── index.d.ts
│     |    └── hooks
│     │         └── useCounter.d.ts
│     ├── index.qwik.cjs
│     ├── index.qwik.mjs
...

Y este es el contenido de nuestra librería compilada dentro de del directorio dist, siendo el resultado de lo que subiríamos a NPM.

Cuando hagamos el proceso de ejecutar las opciones de publicación tanto en local (npm pack) como en producción (npm publish) se ignorarán los ficheros correspondientes a:

Y esto es porque se ha definido anteriormente en el package.json en la propiedad files.

...
"files": [
  "dist", // Este si se añade 
  "!dist/types/root.d.ts", // NO se añade por tener delante "!"
  "!dist/types/entry.dev.d.ts", // NO se añade
  "!dist/types/entry.ssr.d.ts" // No se añade
],
...

Ahora vamos a pasar al apartado de producción, generando el paquete a partir del resultado de la compilación, con el objetivo de distribuirlo en local para ver que funciona todo correctamente antes de enviarlo a NPM.

Consideraciones después de desarrollar la biblioteca

Una vez que ya hemos probado nuestros componentes, hooks y otros elementos, es hora de pensar en enviarlo a producción.

Antes de subirlo directamente a NPM (o Github Packages), es interesante que podamos generar el paquete localmente y consumirlo instalándolo en otro proyecto que vamos a crear desde cero para acercarnos lo máximo posible a lo que se daría en una situación real respecto a consumir un paquete de NPM.

Crear la compilación de producción

La compilación de producción debería generar la versión de producción de nuestra librería de componentes en ./dist y las definiciones de tipo de TypeScript en ./dist/types, apartado que acabamos de ver con más detalle.

npm run build

Si queremos probarlo en un entorno de producción simulado, es decir, creando una nueva app independiente, primero debemos crear el archivo tgz localmente.

Esto sería prácticamente lo mismo que tratar de instalar un paquete desde cualquier repositorio como NPM, pero en este caso lo haremos con la referencia del archivo (absoluta o relativa, es indiferente) con extensión tgz y será en local.

Crear nuestro paquete *.tgz

Para crear el paquete compilado con la extensión tgz, primero debemos asegurarnos de que la versión de nuestro paquete y su nombre sean los correctos, ya que hay unas reglas a cumplir.

Lista de reglas que debemos cumplir para validar el nombre paquete NPM:

  • Longitud mayor que cero.

  • Todos los caracteres deben estar en minúsculas, es decir, no se permiten nombres en mayúsculas o mayúsculas y minúsculas.

  • Puede contener guiones.

  • No debe contener caracteres que no sean seguros para URL (ya que el nombre termina siendo parte de una URL). ¿Cuáles son? Los caracteres a los que se hace referencia serían los siguientes: Espacio, <, >, ", #, % y |.

  • No debe comenzar con . o _.

  • No debe contener espacios (mencionado en los caracteres NO seguros para la URL).

  • No debe contener ninguno de los siguientes caracteres: ~)('!*.

  • No puede ser el mismo que un módulo principal de ni un nombre reservado o incluido en la lista negra. Por ejemplo, los siguientes nombres no son válidos: http, stream, node_modules, favicon.ico.

  • Longitud máxima 214 caracteres.

  • A la hora de publicar en NPM, no debe de existir. Aunque cumplamos las demás condiciones, si ya está cogido el nombre, debemos de cambiarlo por uno que no esté ocupado.

¿Cómo comprobar si existe o no su nombre en NPM?

Cogemos el nombre que hemos asignado a nuestro paquete, desde el package.json en la propiedad name y lo introducimos en nuestro navegador con este formato:

https://www.npmjs.com/package/<NOMBRE_DE_NUESTRO_PAQUETE>

Si el valor de <NOMBRE_DE_NUESTRO_PAQUETE> es @builder.io/qwik (que existe) debemos de introducir la siguiente URL: https://www.npmjs.com/package/@builder.io/qwik

Y si existe ese paquete (como es el caso), nos aparecerá su página principal, con su información de versión, instrucciones del README,...

Si <NOMBRE_DE_NUESTRO_PAQUETE> es anartz como a día de hoy no existe, nos aparecerá una ventana con el error 404, Not Found, advirtiéndonos que ese paquete no existe:

En este caso, tenemos vía libre, por lo que está disponible ese nombre de paquete para publicarlo.

¿Cómo gestionar el apartado del versionado?

Aparte de tener en cuenta el nombre del paquete, debemos de tener en cuenta el tema de gestionar las versiones, donde vamos a trabajar con la convención de versionado semántico , que es un tema que a veces no se suele gestionar bien, por eso, os voy a dar las claves para hacer un versionado correcto.

Referencia a tener en cuenta

Para ampliar el tema sobre el versionado semántico se proporciona el enlace a la documentación oficial:

https://shorten-up.vercel.app/WMeWgceXuZ

La estructura del versionado de cualquier aplicación NPM sería el siguiente:

MAJOR.MINOR.PATCH

El número de esta version se incrementará teniendo en cuenta estos factores:

  • La versión MAJOR cuando se realizan cambios incompatibles en la API.
  • La versión MINOR cuando se agrega funcionalidad de manera compatible hacia atrás.
  • La versión PATCH cuando se realizan correcciones de errores compatibles hacia atrás.

Además, se pueden usar etiquetas adicionales para pre-lanzamientos y metadatos de compilación como extensiones del formato MAJOR.MINOR.PATCH.

Esto se gestionará para cada nueva versión (que se vaya a publicar en NPM o Github Packages), agregando el valor correspondiente según lo que se haya realizado, si se han realizado cambios menores o más relevantes.

Recuerda que siempre tiene que ser superior que la versión anterior.

Por ejemplo, imaginando que actualmente nuestro paquete se encuentra en la versión 1.0.0:

  • De 1.0.0 a 1.0.1 (Válido): Se ha aplicado una corrección de errores compatible hacia atrás.

  • De 1.0.0 a 0.1.0 (Inválido): En este caso está intentando asignar una versión inferior y eso no es posible.

Si deseamos consumir la biblioteca creada, necesitamos generar el archivo *.tgz, el cual se generará con el siguiente formato: <nombre paquete>.<version-paquete>.tgz (nombre del paquete (name) y versión (version) definidos en el archivo package.json).

Si nuestro paquete tiene los siguientes datos en el archivo package.json:

  • name: qwik-template-library

  • version: 1.0.0

Al ejecutar npm run pack, se generará un archivo llamado qwik-template-library-1.0.0.tgz.

Este script pack va a ejecutar las siguientes ordenes del script de manera consecutiva:

# 1.- Elimina el directorio dist con ficheros compilados (si existe) y limpia caché
rm -rf dist && npm cache clean --force

# 2.- Compilar el código como en el paso anterior 
# generando index.qwik.mjs y index.cjs entre otros
npm run build

# 3.- Crear un fichero tgz con todo el contenido de 
# dist, ignorando los ficheros especificados en el package.json
npm pack

Si todo va bien, debería de aparecer el fichero en el apartado de ficheros y directorios de nuestro proyecto:

Ahora va a tocar consumir el paquete localmente desde otro proyecto independiente. Cogemos el fichero qwik-template-library-0.0.1.tgz y lo copiamos para pegarlo en la raíz del nuevo proyecto (Ya sabéis el proceso de crearlo).

Cómo consumir el paquete generado para probarla localmente

Antes de consumir el paquete, creamos el nuevo proyecto de Qwik, en la recién salida versión 1.2.12 (26/09/2023)

npm create qwik@1.2.12

Una vez creado el nuevo proyecto, traemos a la raíz de este el fichero generado con los componentes de nuestra librería:

Con esto, vamos a facilitar su instalación.

Con esto lo instalaremos mediante la ruta relativa (también es posible la absoluta) del fichero qwik-template-library-1.0.0.tgz que contiene los ficheros de la librería que nos permitirá consumirla en la nueva aplicación.

Ejecutamos este comando, teniendo en cuenta que está en el propio proyecto nuevo:

npm i <RUTA del paquete tgz>
    
# si hemos colocado el archivo en el directorio 
# raíz de nuestro nuevo proyecto
npm i qwik-template-library-1.0.0.tgz

Si todo ha ido bien, deberíamos de tener algo de este estilo:

Una vez instalado el paquete de NPM, podemos probarlo, basándonos en lo añadido en el fichero src/root.tsx.

Accedemos al fichero src/routes/index.tsx y dejamos el fichero de la siguiente forma:

// 1.- Importamos los componentes de nuestra librería personalizada
// haciendo referencia al paquete (tenemos en cuenta el valor de "name")
import { Counter , Hello, Logo } from 'qwik-template-library';
import { component$ } from "@builder.io/qwik";

// 2.- Añadimos los componentes como en src/root.tsx del proyecto de la librería
export default component$(() => {
  return (
    <>
      <h1>Testing with custom Qwik Library 👋</h1>
      <Logo
        url='https://qwik.builder.io/'
        alt='Qwik Logo'
        width={400}
        height={147}
        image='https://cdn.builder.io/api/v1/image/assets%2FYJIGb4i01jvw0SRdL5Bt%2F667ab6c2283d4c4d878fb9083aacc10f'
      />
      <h4><code>{`<Counter />`}</code> component with <code>{`useCounter`}</code> custom hook</h4>
      <Counter />
      <br/><br/><br/>
      <Hello />
    </>
  );
});

Al guardar, ejecutamos para iniciar el proyecto y debería de mostrarse lo siguiente:

Con esto, hemos comprobado que la librería es correcta y podemos ir con seguridad a publicarla en NPM.

Publicar el paquete

Para poder publicar el paquete, debemos de tener en cuenta algunos ajustes, como el nombre del paquete, el versionado semántico y que ese paquete, que aunque tenga un nombre válido, no exista.

Esta consideraciones ya las hemos tomado, por lo que podemos afirmar que ya tenemos preparado nuestro paquete para publicarlo.

Una vez comprobados esos aspectos, lo que tenemos que hacer para publicarlo es ejecutar el comando npm publish.

El nombre del paquete (después de cambiarlo en el fichero package.json en la propiedad name) que voy a publicar se va a llamar qwik-example-lib, por lo que en el momento que se publique podremos encontrar toda su información en https://www.npmjs.com/package/qwik-example-lib

Obviamente, si usáis este nombre, como mi paquete va a estar publicado, no lo podréis publicar por estar ocupado por mí.

Lo ejecutamos, y si no estamos logueados con nuestros credenciales de NPM, nos los pedirán. Debemos de introducir:

Si todo va bien, este sería el flujo de lo que debería ocurrir en nuestra librería:

Y accedemos a https://www.npmjs.com/package/qwik-example-lib, para comprobar que si se ha publicado:

A tener en cuenta en la primera publicación

Os recomiendo que comprobéis si debéis actualizar los campos de package.json, como name, version, description, etc. Así evitaremos tener que versionar para meter cambios únicamente del fichero package.json o el README.md.

Fundamental recordar los tres aspectos mencionados como asignar un nombre correcto, versión y que no exista.

Ya tenemos la librería publicada, ¡¡este es el primer paso a grandes desarrollos!!

¿Nos falta algo para terminar? Aunque sea opcional, es recomendable consumir la librería instalando el paquete haciendo referencia a NPM.

Consumiendo nuestro paquete NPM

Volvemos al proyecto donde hemos instalado el fichero con extensión tgz donde teníamos el contenido de nuestra librería que hemos acabado de publicar.

Vamos al terminal y añadimos:

npm install qwik-example-lib

Una vez instalado el paquete, sustituimos en src/routes/index.tsx, lo siguiente:

import { Counter , Hello, Logo } from 'qwik-template-library';

Por lo siguiente ya que ahora el nombre del paquete publicado en su package.json es qwik-example-lib:

import { Counter , Hello, Logo } from 'qwik-example-lib';

Ejecutamos el proyecto y este debería de seguir funcionando de la misma forma, ya que no se han realizado cambios en los componentes.

El resultado es prácticamente el mismo.

Con esto, se puede dar por finalizado este capítulo.

CLI crear proyectos librería

Antes de finalizar el capítulo, os presento un CLI creado por mi mismo, en base a la plantilla inicial que hemos usado para el tutorial.

Una de las características destacadas de este CLI es la capacidad de seleccionar plantillas predefinidas para la creación de la librería.

Actualmente, el CLI ofrece tres plantillas diferentes (puede que se haya ampliado y seguramente mejorado) donde os expongo su objetivo y os enseño su vista previa con el código en marcha:

Referencia del artículo mencionado de mapas

A continuación os proporciono el enlace del artículo donde se enseña a integrar mapas de Leaflet con Qwik:

https://shorten-up.vercel.app/9KgLXRE4T0

Opciones que nos proporciona el CLI

Una vez que se completan los pasos iniciales y se selecciona una plantilla, el CLI se encargará de generar automáticamente los directorios y archivos necesarios basados en la plantilla elegida.

¿Qué significa esto? Es sencillo, a partir de introducir los datos requeridos no vamos a tener que preocuparnos por la generación de la estructura de carpetas y archivos, ya que la herramienta se encargará de crearlos por nosotros mismos.

Además, el CLI también instalará automáticamente todas las dependencias requeridas para comenzar a trabajar con la librería. Esto nos va a hacer ahorrar tiempo y esfuerzo al evitar la necesidad de configurar manualmente las dependencias una por una.

Os animo a hacer uso de este CLI y a contribuir con el proyecto (https://shorten-up.vercel.app/wJkXEZr-hB) con nuevos templates y mejoras.

Todas las instrucciones de uso las encontraréis en ese repositorio que os he añadido.

Resultado de lo trabajado en este capítulo

El código que encontráis es el resultado final de todo el proceso realizado durante el capítulo. Os recomiendo que vayáis haciendo los pasos poco a poco y paso a paso para ir interiorizando todos los conceptos y en este caso, pienso que os vendría bien realizar pruebas con más ejemplos.

https://shorten-up.vercel.app/QMN_G1ATXF

Librería publicada en NPM:
https://shorten-up.vercel.app/EyUalNKwpm

CLI para crear librerías de manera sencilla y ágil:
https://shorten-up.vercel.app/-vWdkY_vS_

¿Qué hemos aprendido en este capítulo?

Al finalizar este capítulo, deberíamos de ser capaces de:

Conclusión

Llegados a este punto sabemos el proceso detallado para crear librerías en Qwik y como publicarlas.

Lo que nos faltaría es darle más mimo al apartado de las instrucciones que se redactan en el README.md para que cualquier persona que consuma nuestra librería pueda hacerlo sin problemas y detalles como añadir un fichero de licencia, pero este no es el objetivo en este punto.

En lo demás, os he enseñado todos los trucos para poder desarrollar una librería y como hacer el proceso de pruebas, paso a paso, antes de publicarla en producción.