Construyendo una navaja suiza: Cómo reutilizar código con paquetes y un repositorio único

Construyendo una navaja suiza: Cómo reutilizar código con paquetes y un repositorio único

En este artículo, discutimos cómo reutilizar el código con paquetes privados/públicos usando un monorepo para escalar la funcionalidad de la aplicación JavaScript.

Exploramos dos soluciones: múltiples repositorios y un solo repositorio (monorrepo) y optamos por la segunda opción, introduciendo algunas herramientas como Turborepo y Changeset para ayudar a administrar un monorrepo de manera eficiente. Luego construimos una arquitectura con varias aplicaciones y paquetes, ideal para empresas con múltiples aplicaciones y componentes compartidos que buscan un enfoque escalable para el desarrollo de software.

El problema que se discutirá en este artículo es cómo reutilizar código con paquetes privados/públicos usando un monorrepo para escalar la funcionalidad de tus aplicaciones JavaScript.

Es muy común que las empresas tengan más de una aplicación, por ejemplo:

1) Aplicación para el cliente (CLIENT).

2) Aplicación para administración del sistema (ADMIN).

3) Otras aplicaciones.

Con estas aplicaciones, definitivamente habrá cierta superposición de código. Por ejemplo: componentes básicos que se pueden compartir usando el famoso Design System.

Este Sistema de Diseño puede ser un paquete interno de la empresa, o incluso público. Además, estas aplicaciones pueden consumir APIs similares y podemos tener un SDK que implemente las llamadas para facilitar su uso.

Con esto en mente, ¿cómo podemos organizar y construir nuestra navaja suiza?

  • Una solución sería tener múltiples repositorios para cada aplicación y paquete; y cargar los paquetes en NPM Packages o GitHub Packages.
  • Esta solución puede ser buena cuando la empresa tiene varios equipos y quiere restringir el acceso a los códigos, pero puede ser muy laboriosa para equipos pequeños cuando la arquitectura aún no está muy madura, ya que el desarrollo local requiere el uso de enlaces simbólicos (yarn link o npm link) para hacer referencia a paquetes y desarrollo local.
  • Otra solución es tener un monorrepo (repositorio único) con aplicaciones y paquetes que se pueden publicar en NPM Packages o GitHub Packages (también se pueden usar localmente porque están en el mismo repositorio).
  • Esta solución es muy buena para equipos pequeños que inician su sistema de diseño y arquitectura de API, con el objetivo de contar con un código desacoplado y el intercambio futuro de paquetes públicos.

En este artículo usaremos la segunda opción, pero primero definiremos algunos conceptos y herramientas:

  • Un Monorrepo (repositorio monolítico) es un modelo de gestión de código fuente en el que todo el código de una organización se almacena en un solo repositorio, en lugar de dividirse en múltiples repositorios más pequeños para cada proyecto. El objetivo es simplificar la gestión del código y permitir una colaboración más fácil y eficiente entre los equipos.
  • Turborepo es una biblioteca de JavaScript que ayuda a administrar monorrepos. Proporciona herramientas para hacer frente a las complejidades de trabajar con varios proyectos en un único repositorio, como la gestión de dependencias, el control de versiones de paquetes y la gestión de compilaciones. Con Turborepo, puedes crear, probar y publicar paquetes en un monorrepo de manera más eficiente y segura.
  • La biblioteca Changeset es una extensión del ecosistema monorrepo, diseñada para simplificar la forma en que se rastrean y administran los cambios de código en un repositorio monolítico. Con Changeset, los desarrolladores pueden agrupar cambios en conjuntos (llamados changesets) y asignar esos conjuntos a paquetes específicos en un monorepo.

¡Manos a la obra! Construyamos la siguiente arquitectura:

  • App Client: Aplicación Vite para el cliente;
  • App Admin: Aplicación Vite para el admin;
  • Package Core Api SDK: Paquete SDK para uso de las apis;
  • Package ESLint Config: Paquete para compartir las configuraciones de eslint;
  • Package TS Config: Paquete para compartir las configuraciones de typescript;
  • Package Design System: Paquete para compartir componentes UI.


Paso a paso

1) Haz un fork o copia el repositorio base.

Repo: https://github.com/kibolho/monorepo-scaffold

Tu repositorio puede ser público o privado, depende de cómo quieras tu proyecto. Solo recuerda que ciertas funciones en la cuenta gratuita solo están disponibles para repositorios públicos como GitHub Pages. Conoce más.

2) Crea una clave de acceso personal.

Necesitarás esta clave de acceso personal para crear tus paquetes. Por lo tanto, créala con los siguientes accesos (conoce más):

3) Agrega la clave creada como un secreto en el repositorio.

Guarda la clave que generaste como un secreto en el repositorio para que la consuman las actions  en el flujo de deploy del paquete. Nombre sugerido: GH_REGISTRY_PACKAGES. Este nombre se utilizará en el workflow de deploy. Conoce más.

4) Añade permisos en tu repositorio para el workflow.

Tu workflow de implementación de paquetes deberá leer y escribir en el repositorio además de crear pull request para aprobar nuevas versiones. Conoce más.

5) Agrega permisos en tu repositorio para GitHub Pages.

Como necesitamos construir nuestros assets antes del deploy, vamos a usar Github Actions. Para esto, es necesario dar permiso para que el flujo de trabajo cargue los assets en las páginas de GitHub. Conoce más.

6) Clona tu repositorio en tu equipo.

Ejecuta el siguiente comando (conoce más):

git clone git@github.com:kibolho/monorepo-scaffold.git


7) Aumenta o actualiza la versión de tu paquete.

Ejecuta el siguiente comando:

yarn changeset

8) Deploy.

Ahora solo falta comprometer (commit) y los workflows se añadirán.


9) Aprobar el pull request creado por Changeset.


10) Paquete creado y listo para ser usado.

Ahora tenemos el paquete creado y puede descargarse usando registry de GitHub.


11) Usar el paquete.

El registry padrón es NPM, entonces para descargar el paque de GitHub es preciso apuntarse para el registry de GitHub.

En caso de que quieras usar los paquetes de forma privada: Crea o edita el archivo ~/.npmrc e substitua PERSONAL-ACCESS-TOKEN en tu token generado en el paso 2. El archivo ~/.npmrc es responsable de las configuraciones globales de NPM.

//npm.pkg.github.com/:_authToken=PERSONAL-ACCESS-TOKEN

Como puedes ver, el foco estuvo más en la arquitectura. No profundicé tanto en el código porque son muchas tecnologías involucradas. ¡Quizás en los próximos artículos sí las aborde!

Algunas observaciones:

  • La aplicación Client en el código quedó solamente con Hello World de Vite, ya que el concepto se mostraba en la aplicación Admin;
  • Creé un workflow que hace el deploy de la aplicación Cliente y Administrador en S3 en diferentes buckets, ya que las páginas de GitHub no admiten varias aplicaciones por repositorio. Sigue esta sugerencia de función aquí.

Como el repositorio es público, queda a discreción proponer mejoras 😀 como:

  • Hacer el deploy en Vercel;
  • Optimizar los paquetes design-system y api-core-sdk con apis públicas;
  • Crear una aplicación real encima de la arquitectura.

Aplicación Admin Final - https://kibolho.github.io/monorepo-scaffold/

¡Hasta la próxima!

💡
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Listopro.

Listopro Community da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.