Estructura de `node_modules` con enlaces simbólicos
Este artículo solo describe cómo se estructuran la carpeta node_modules
de pnpm cuando no hay paquetes con dependencias pares. Para el escenario más complejo de dependencias pares, revise cómo se resuelven las dependencias pares.
El diseño de la carpeta node_modules
de pnpm utiliza enlaces simbólicos para crear una estructura anidada de dependencias.
Cada archivo de un paquete dentro de node_modules
es un vínculo al almacenamiento de contenido direccionable. Digamos vas a instalar foo@1.0.0
el cual depende de bar@1.0.0
. pnpm creará un vínculo a estos paquetes en node_modules
esta manera:
node_modules
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
│ ├── index.js
│ └── package.json
└── foo@1.0.0
└── node_modules
└── foo -> <store>/foo
├── index.js
└── package.json
Estos son los únicos archivos "reales" en node_modules
. Una vez que todos los paquetes están vinculados a la carpeta node_modules
, los enlaces simbólicos son creados para construir la estructura del gráfico de las dependencias anidadas.
Como habrás notado, ambos paquetes están vinculados a una sub carpeta dentro de una carpeta node_modules
, así: (foo@1.0.0/node_modules/foo
). Esto es necesario para:
- Permitir que los paquetes se importen solos. El paquete
foo
debería poderrequire('foo/package.json')
oimport * as package from "foo/package.json"
. - evitar enlaces simbólicos circulares. Las dependencias de los paquetes se colocan en la misma carpeta en la que se encuentran los paquetes dependientes. Para Node.js, no hace ninguna diferencia si las dependencias están dentro de la carpeta
node_modules
del paquete o en cualquier otronode_modules
en los directorios superiores.
La siguiente etapa de la instalación es la creación de los enlaces simbolicos de las dependencias. bar
va a estar vinculado simbólicamente a la carpeta foo@1.0.0/node_modules
:
node_modules
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
└── foo@1.0.0
└── node_modules
├── foo -> <store>/foo
└── bar -> ../../bar@1.0.0/node_modules/bar
A continuación, se manejan las dependencias directas. foo
se vinculará simbólicamente a la carpeta raíz node_modules
debido foo
es una dependencia del proyecto:
node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ └── bar -> <store>/bar
└── foo@1.0.0
└── node_modules
├── foo -> <store>/foo
└── bar -> ../../bar@1.0.0/node_modules/bar
Este es un ejemplo muy simple. Sin embargo, el diseño mantendrá esta estructura independientemente del número de dependencias y la profundidad del gráfico de dependencia.
Agreguemos qar@2.0.0
como una dependencia de bar
y foo
. Así es como se verá la nueva estructura:
node_modules
├── foo -> ./.pnpm/foo@1.0.0/node_modules/foo
└── .pnpm
├── bar@1.0.0
│ └── node_modules
│ ├── bar -> <store>/bar
│ └── qar -> ../../qar@2.0.0/node_modules/qar
├── foo@1.0.0
│ └── node_modules
│ ├── foo -> <store>/foo
│ ├── bar -> ../../bar@1.0.0/node_modules/bar
│ └── qar -> ../../qar@2.0.0/node_modules/qar
└── qar@2.0.0
└── node_modules
└── qar -> <store>/qar
Como puede ver, aunque el gráfico es más profundo ahora (foo > bar > qar
), la profundidad de los directorios en el sistema de archivos sigue siendo la misma.
Este diseño puede parecer extraño a primera vista, ¡pero es completamente compatible con el algoritmo de resolución de módulos de Node! Al resolver módulos, Node ignora enlaces simbólicos, por lo que cuando se requiere bar
de foo@1.0.0/node_modules/foo/index.js
, Node no usa bar
en foo@1.0.0/node_modules /bar
, pero en su lugar, bar
se convierte a su ubicación real (bar@1.0.0/node_modules/bar
). Como consecuencia, bar
también puede resolver sus dependencias que se encuentran en bar@1.0.0/node_modules
.
Una gran ventaja de este diseño es que solo los paquetes que realmente están en las dependencias son accesibles. Con una estructura plana de la carpeta node_modules
, se puede acceder a los paquetes superiores. Para obtener más información sobre por qué esto es una ventaja, consulte "El rigor de pnpm ayuda a evitar errores desagradables"