Deja de Copiar y Pegar: Mi Enfoque Práctico para Reutilizar Código con un Monorepo
Te cuento cómo dejé de duplicar código en mis proyectos y aceleré mi desarrollo de forma radical. Descubre mi enfoque práctico usando un monorepo privado, sus ventajas y cómo puedes implementarlo hoy mismo.
Si llevas un tiempo creando productos digitales, seguro que te suena esta situación: estás empezando un nuevo proyecto y te das cuenta de que necesitas, otra vez, esa misma lógica de autenticación, esos componentes de UI o esa librería de utilidades que ya escribiste para otro cliente hace tres meses. ¿Qué haces? Lo más rápido: abres el proyecto antiguo, copias y pegas.
Yo lo he hecho. Todos lo hemos hecho. Y es una de las peores deudas técnicas que podemos acumular.
El problema que todos ignoramos
Copiar y pegar es una solución a corto plazo que crea un infierno de mantenimiento a largo plazo. De repente, encuentras un bug en ese módulo de autenticación. Ahora tienes que recordaren qué cinco proyectos lo pegaste y arreglarlo en todos ellos. Inevitablemente, se te olvida uno. Las versiones empiezan a divergir. Lo que era un solo código ahora son cinco copias ligeramente distintas y rotas de formas únicas.
Es ineficiente, propenso a errores y, francamente, un desperdicio de tu talento.
Los caminos que no me funcionaron del todo
Buscando una solución, exploré las opciones 'correctas':
1. Paquetes privados (NPM, Composer, etc.): Es la solución de libro. Empaquetas tu código compartido, lo publicas en un registro privado y lo instalas como una dependencia en tus proyectos. * El problema: Para un solo desarrollador o un equipo pequeño, el overhead es brutal. Cada vez que haces un pequeño cambio en el paquete, tienes que versionar, publicar, y luego actualizar la dependencia en cada proyecto. Rompe el flujo de trabajo y añade una fricción innecesaria para cambios rápidos.
2. Submódulos de Git: Otra opción teóricamente buena. Permite anidar un repositorio dentro de otro. * El problema: Si has trabajado con submódulos, sabes que pueden ser... temperamentales. La gestión del estado entre el repo principal y el submódulo puede volverse confusa rápidamente, sobre todo cuando trabajas en ambos a la vez.
Necesitaba algo más simple, más directo.
La solución: Un monorepo privado y pragmático
Aquí es donde encontré mi punto ideal: el monorepo. Un solo repositorio de Git que contiene todos mis proyectos y todo mi código compartido.
No hablo de los monorepos gigantescos de Google o Facebook con herramientas a medida. Hablo de una estructura simple y lógica que cualquiera puede montar en cinco minutos.
¿Por qué funciona tan bien para mí?
- Cero fricción: Todos los proyectos y librerías están en el mismo sitio. Un `git clone` y lo tienes todo. Un cambio en una librería compartida está disponible *instantáneamente* para todos los proyectos que la usan. No hay que publicar ni actualizar nada.
- Commits atómicos: Puedo hacer un cambio en mi librería de UI y, en el mismo commit, actualizar el proyecto que la consume para que refleje ese cambio. Esto es increíblemente potente. Garantiza que la base de código siempre esté en un estado consistente.
- Refactorización global: Mi editor de código (VSCode en mi caso) ve todo como un gran proyecto. Puedo renombrar una función en una librería compartida y el editor la refactorizará automáticamente en todos los proyectos que la utilizan. Una maravilla.
- Simplicidad en la gestión: Un solo lugar para gestionar issues, pull requests y la configuración de linting o formateo.
Mi estructura y herramientas
Mi enfoque es deliberadamente minimalista. Así es como suelo estructurar mis monorepos (en este ejemplo, para un ecosistema JavaScript/TypeScript):
/mi-empresa-monorepo
├── /apps
│ ├── /web-cliente-a
│ ├── /api-principal
│ └── /docs-landing
│
├── /packages
│ ├── /ui-components (Componentes de React/Vue/Svelte)
│ ├── /auth-logic (Lógica de autenticación compartida)
│ ├── /eslint-config-custom (Configuración de ESLint para todos)
│ └── /utils (Funciones de ayuda genéricas)
│
└── package.json (El package.json raíz que gestiona todo)
La magia que une todo esto son los workspaces (disponibles en `npm`, `yarn` y `pnpm`). En el `package.json` raíz, defines dónde están tus paquetes y aplicaciones. La herramienta de línea de comandos se encarga de 'enlazar' simbólicamente los paquetes dentro de `node_modules` de tus aplicaciones.
Para proyectos más grandes, herramientas como Turborepo o Nx llevan esto al siguiente nivel, optimizando los builds y los tests para ejecutar solo lo que ha cambiado, pero para empezar, los workspaces nativos son más que suficientes.
No todo es perfecto: Las desventajas
Sería deshonesto no mencionar los contras:
- Tamaño del repositorio: Con el tiempo, el repositorio puede crecer bastante. Un `git clone` inicial puede ser más lento.
- Builds y CI/CD: La configuración de la integración continua es un poco más compleja. Tienes que configurar tus pipelines para que entiendan qué ha cambiado y solo construyan o desplieguen las aplicaciones afectadas.
- Acoplamiento: Existe el riesgo de acoplar demasiado los proyectos si no eres disciplinado. Hay que tratar los `packages` como si fueran librerías externas, con APIs bien definidas.
Conclusión: Pragmatismo sobre dogma
Para mí, como emprendedor y desarrollador que gestiona múltiples productos y proyectos de clientes, el monorepo ha sido un cambio de juego. Las ventajas en velocidad y consistencia superan con creces las desventajas.
No es la solución para todas las empresas ni para todos los equipos. Pero si eres un lobo solitario o parte de un equipo pequeño y ágil, te animo a que lo pruebes. Deja de luchar contra la duplicación de código y empieza a construir un sistema que trabaje para ti, no en tu contra. A veces, la solución más práctica es la mejor.