
En los últimos años, el concepto de 
mono-repositorios se ha establecido 
con éxito, ya que puede simplificar significativamente el proceso de desarrollo de proyectos de software modular, como las infraestructuras basadas en microservicios. Las principales ventajas de este enfoque arquitectónico son obvias en la práctica, por lo tanto, propongo crear su propio 
mono-repositorio de prueba desde cero, al mismo tiempo que comprende los matices de trabajar con 
espacios de trabajo de hilo y 
lerna . Bueno, empecemos!
Considere la estructura de nuestro proyecto, que serán tres bibliotecas ubicadas en la carpeta 
paquetes / , así como 
package.json en el directorio raíz.
├── package.json └── packages ├── app │  ├── index.js │  └── package.json ├── first │  ├── index.js │  └── package.json └── second ├── index.js └── package.json 
Se entiende que tenemos dos bibliotecas independientes 
primero y 
segundo , así como una biblioteca de 
aplicaciones que importará funciones de las dos primeras. Por conveniencia, los tres paquetes se colocan en el directorio de 
paquetes . Puede dejarlos en la carpeta raíz o ponerlos en un directorio con cualquier otro nombre, pero para seguir las convenciones generalmente aceptadas, los colocaremos de esta manera.
Las bibliotecas 
primero y 
segundo para simplificar el experimento contendrán solo una función en 
index.js , cada una de las cuales devolverá una cadena de saludo en nombre del módulo. Para el 
primer ejemplo, se verá así:
 
En el módulo de la 
aplicación , mostraremos el mensaje 
Hola desde la aplicación en la consola, así como saludos desde otros dos paquetes:
 
Para que el 
primero y el 
segundo estén disponibles en la 
aplicación , los denotamos como dependencias en 
dependencias .
Además, para cada biblioteca agregamos el prefijo 
@ monorepo / en el 
nombre del valor delante del nombre principal del paquete al paquete 
local.json .
 
¿Por qué necesito un prefijo con un icono de perro delante del nombre del paquete npm (@ monorepo /)?Agregar un prefijo es opcional, pero esta 
es exactamente 
la convención de denominación 
de paquetes a la que se adhieren muchos monorepositorios:
material ui , 
angular y otros. El hecho es que cada usuario u organización tiene su propio 
alcance en el 
sitio web 
npm , por lo que hay una garantía de que todos los módulos con 
@ somescope / postfix son creados por el equipo de 
somescope y no por los atacantes. Además, se hace posible llamar a los nombres de módulos que ya están en uso. Por ejemplo, no puede simplemente tomar y crear su propio módulo de 
utilidades , porque esa biblioteca 
ya existe . Sin embargo, agregando el postfix 
@ myscopename / podemos obtener nuestras 
utilidades ( 
@ myscopename / utils ) con blackjack y señoritas.
 Un análogo de la vida real para nuestro proyecto de prueba puede ser varias bibliotecas para trabajar con datos, herramientas de validación, análisis o simplemente un conjunto de componentes de la interfaz de usuario. Si suponemos que vamos a desarrollar una aplicación 
web y 
móvil (por ejemplo, usando 
React y 
React Native, respectivamente), y tenemos parte de la lógica reutilizada, puede valer la pena ponerla en componentes separados, para su uso posterior en otros proyectos. Agregue a esto el servidor en 
Node.js y obtendrá un caso muy real de la vida.
Espacios de trabajo de hilo
El toque final antes de crear un 
repositorio mono completo será el diseño de 
package.json en la raíz de nuestro repositorio. Preste atención a la propiedad de 
espacios de trabajo : especificamos el valor de los 
paquetes / * , que significa "todas las subclaves en la carpeta de 
paquetes ". En nuestro caso, esta es la 
aplicación , 
primero , 
segundo .
 
Además, 
"private": true debe especificarse en 
package.json , ya que los 
espacios de trabajo solo están disponibles en proyectos privados.
Para que todo despegue, ejecute el comando 
yarn (de forma análoga a 
yarn install o 
npm install ) desde el directorio raíz. Dado que las dependencias que existen en el módulo de la 
aplicación se definen como 
espacios de 
trabajo en el 
paquete raíz.json , de hecho, no descargaremos nada de 
npm-Registry , sino que simplemente 
enlazaremos (" 
enlazaremos ") nuestros paquetes.
 yarn 

Ahora podemos ejecutar el comando del 
nodo. desde el directorio raíz que ejecutará el script desde el 
archivo packages / app / index.js .
 node . 

Veamos como funciona. 
Al llamar a 
yarn , creamos enlaces simbólicos en 
node_modules a nuestros directorios en la carpeta de 
paquetes .

Debido a esta relación en las dependencias, obtuvimos una gran ventaja: ahora, al cambiar en el 
primer y 
segundo módulo, nuestra 
aplicación recibirá la versión actual de estos paquetes sin reconstruirla. En la práctica, es muy conveniente, porque podemos llevar a cabo el desarrollo local de paquetes, aún definiéndolos como dependencias de terceros (que eventualmente se convierten).
La siguiente ventaja importante que puede obtener al trabajar con 
espacios de trabajo de hilo es la organización del almacenamiento de dependencias de terceros.
Obtenga más información sobre el almacenamiento de dependencias en el nivel superior.Supongamos que queremos usar la biblioteca 
lodash en 
primer y 
segundo lugar . 
Al ejecutar el comando yarn add lodash desde los directorios apropiados, recibiremos una actualización del 
paquete local.json : la versión actual del paquete aparecerá en las 
dependencias .
 "dependencies": { "lodash": "^4.17.11" } 
En cuanto al paquete 
lodash en sí , físicamente la biblioteca se instalará en 
node_modules en el nivel raíz una vez.
Si la versión requerida del paquete externo (en nuestro caso 
lodash ) es diferente para el 
primero y el segundo (por ejemplo, 
primero necesita 
lodash v3.0.0 , y en el 
segundo v4.0.0 ), entonces un paquete con una versión inferior ( 
3.0.0 ) llegará a la raíz 
node_modules , y la versión 
lodash para el 
segundo módulo se almacenará en 
paquetes locales 
/ second / node_modules .
Además de las ventajas, este enfoque puede tener desventajas menores, que el 
hilo permite evitar con la ayuda de banderas adicionales. Puede leer más sobre tales matices en la 
documentación oficial .
 Añadir Lerna
El primer paso para trabajar con 
lerna es instalar el paquete. Por lo general, realizan una instalación global ( 
yarn global add lerna o 
npm i -g lerna ), pero si no está seguro de si desea usar esta biblioteca, puede usar la llamada usando 
npx .
Inicializaremos 
lerna desde el directorio raíz:
 lerna init 

De hecho, realizamos varias acciones a la vez con la ayuda de un comando: creamos un repositorio git (si no se había inicializado antes), creamos un archivo 
lerna.json y actualizamos nuestro 
paquete raíz.json .
Ahora en el archivo 
lerna.json recién creado 
, agregue dos líneas: 
“npmClient”: “yarn” y 
“useWorkspaces”: true . La última línea dice que ya usamos 
espacios de trabajo de hilo y no hay necesidad de crear la 
carpeta app / node_modules con enlaces simbólicos a 
primero y 
segundo .
 
Pruebas con Lerna
Para mostrar la conveniencia de trabajar con 
lerna, agregue pruebas para nuestras bibliotecas.
Desde el directorio raíz, instalamos el paquete para probar - 
jest . Ejecute el comando:
 yarn add -DW jest 
¿Por qué necesito la bandera -DW?El indicador -D (- dev) es necesario para que el paquete jest se instale como una dependencia de desarrollo, y el indicador -W (- ignore-workspace-root-check) permite la instalación en el nivel raíz (que necesitamos).
 El siguiente paso es agregar un archivo de prueba a nuestro paquete. Para la conveniencia de nuestro ejemplo, haremos todas las pruebas similares. Para el 
primer ejemplo, el archivo de prueba se verá así:
 
También necesitamos agregar un script para ejecutar pruebas en 
package.json de cada una de nuestras bibliotecas:
 
El toque final será actualizar el 
paquete raíz.json . Agregue un script de 
prueba que llame a 
lerna run test --stream . El parámetro que sigue a 
lerna run define el comando que se llamará en cada uno de nuestros paquetes desde los 
paquetes / carpeta, y el indicador 
--stream nos permitirá ver la salida de los resultados en el terminal.
Como resultado, 
package.json del directorio raíz se verá así:
 
Ahora, para ejecutar las pruebas, solo necesitamos ejecutar el comando desde la raíz de nuestro proyecto:
 yarn test 

Actualización de versión con Lerna
La próxima tarea popular, con la que 
lerna puede hacer frente a la calidad, será actualizar las versiones del paquete. Imagine que después de implementar las pruebas, decidimos actualizar nuestras bibliotecas de 1.0.0 a 2.0.0. Para hacer esto, simplemente agregue la línea 
"update: version": "lerna version --no-push" al campo de 
scripts del 
paquete raíz.json , y luego ejecute 
yarn update: version desde el directorio raíz. El indicador 
--no-push se agrega para que después de actualizar la versión los cambios no se envíen al repositorio remoto, lo que 
lerna hace por defecto (sin este indicador).
Como resultado, nuestro 
paquete raíz.json se verá así:
 
Ejecute el script de actualización de versión:
 yarn update:version 
A continuación, se nos pedirá que seleccionemos la versión a la que queremos cambiar:

Al hacer clic en 
Entrar , obtenemos una lista de paquetes en los que se actualiza la versión.

Confirmamos la actualización ingresando 
y y recibimos un mensaje sobre la actualización exitosa.

Si tratamos de ejecutar el comando 
git status , no recibimos 
nada para confirmar, trabajando en árbol limpio , porque 
La versión lerna no solo actualiza las versiones del paquete, sino que también crea un git commit y una etiqueta que indica la nueva versión (v2.0.0 en nuestro caso).
Características de trabajar con el equipo de la versión lernaSi agrega la línea 
"versión": "versión lerna --no-push" en lugar de 
"actualización: versión": "versión lerna --no-push" en el campo de los 
scripts del 
paquete raíz.json , lo más probable es que encuentre un comportamiento inesperado y consola roja El hecho es que 
npm-scripts por defecto llama al comando de 
versión (script reservado) inmediatamente después de actualizar la versión del paquete, lo que conduce a una llamada recursiva a la 
versión lerna . Para evitar esta situación, es suficiente darle al script un nombre diferente, por ejemplo, 
actualización: versión , como se hizo en nuestro ejemplo.
 Conclusión
Estos ejemplos muestran una centésima parte de todas las posibilidades que 
lerna tiene en conjunción con 
espacios de trabajo de hilo . Desafortunadamente, hasta ahora no he encontrado instrucciones detalladas para trabajar con monorepositorios en ruso, ¡así que podemos suponer que se ha comenzado!
Enlace al repositorio del proyecto de prueba.