Перейти до основного змісту
Версія: Next

Структура node_modules із символічними посиланнями

інформація

У цій статті описано лише структуру node_modules pnpm за відсутності пакунків з прямими залежностями. Для більш складного сценарію залежностей з прямими залежностями див. як вирішуються проблеми з прямими залежностями.

У pnpm компонування node_modules використовує символічні посилання для створення вкладеної структури залежностей.

Кожен файл кожного пакунка всередині node_modules є жорстким посиланням на сховище з адресованим вмістом. Скажімо, ви встановили [email protected], який залежить від [email protected]. pnpm створить жорстке посилання обох пакунків на node_modules, як показано нижче:

node_modules
└── .pnpm
├── [email protected]
│ └── node_modules
│ └── bar
│ ├── index.js -> <store>/001
│ └── package.json -> <store>/002
└── [email protected]
└── node_modules
└── foo
├── index.js -> <store>/003
└── package.json -> <store>/004

Це єдині «справжні» файли у node_modules. Після того, як усіх пакунків буде створено жорсткі посилання з node_modules, буде створено символічні посилання для побудови структури вкладеного графа залежностей.

Як ви могли помітити, обидва пакунки мають жорсткі посилання на підтеку всередині теки node_modules теки [email protected]/node_modules/foo). Це потрібно для того щоб:

  1. дозволити пакункам імпортувати самих себе. foo повинен мати можливість require('foo/package.json') або import * as package from "foo/package.json".
  2. уникання циклічних символічних посилань. Залежності пакунків розміщуються у тій самій теці, у якій знаходяться залежні пакунки. Для Node.js не має значення, чи знаходяться залежності всередині node_modules пакунка, чи у будь-яких інших node_modules у батьківських теках.

Наступним етапом інсталяції є створення символьних посилань на залежності. bar буде повʼязано з текою [email protected]/node_modules:

node_modules
└── .pnpm
├── [email protected]
│ └── node_modules
│ └── bar -> <store>
└── [email protected]
└── node_modules
├── foo -> <store>
└── bar -> ../../[email protected]/node_modules/bar

Далі обробляються прямі залежності. foo буде приєднано до кореневої теки node_modules, оскільки foo є залежністю проєкту:

node_modules
├── foo -> ./.pnpm/[email protected]/node_modules/foo
└── .pnpm
├── [email protected]
│ └── node_modules
│ └── bar -> <store>
└── [email protected]
└── node_modules
├── foo -> <store>
└── bar -> ../../[email protected]/node_modules/bar

Це дуже простий приклад. Однак макет збереже цю структуру незалежно від кількості залежностей і глибини графа залежностей.

Додамо [email protected] як залежність bar та foo. Ось так виглядатиме нова структура:

node_modules
├── foo -> ./.pnpm/[email protected]/node_modules/foo
└── .pnpm
├── [email protected]
│ └── node_modules
│ ├── bar -> <store>
│ └── qar -> ../../[email protected]/node_modules/qar
├── [email protected]
│ └── node_modules
│ ├── foo -> <store>
│ ├── bar -> ../../[email protected]/node_modules/bar
│ └── qar -> ../../[email protected]/node_modules/qar
└── [email protected]
└── node_modules
└── qar -> <store>

Як ви можете бачити, хоча графік став глибшим (foo > bar > qar), глибина тек у файловій системі залишилася незмінною.

Таке компонування може здатися дивним на перший погляд, але воно повністю сумісне з алгоритмом резолюції модулів Node! Під час перетворення модулів Node ігнорує символічні посилання, тому коли bar вимагається з [email protected]/node_modules/foo/index.js, Node не використовує bar за адресою [email protected]/node_modules/bar, натомість bar перетвориться на його справжнє місцезнаходження ([email protected]/node_modules/bar). Як наслідок, bar також може розвʼязувати свої залежності, які знаходяться у [email protected]/node_modules.

Великим бонусом такої схеми є те, що доступними є лише ті пакунки, які дійсно є у залежностях. Зі сплющеною структурою node_modules всі підняті пакунки є доступними. Щоб дізнатися більше про те, чому це перевага, див. "Суворість pnpm допомагає уникнути прикрих помилок"

На жаль, багато пакунків в екосистемі є пошкодженими — вони використовують залежності, які не вказані у їхньому package.json. Щоб мінімізувати кількість проблем, з якими стикаються нові користувачі, pnpm стандартно підіймає всі залежності у node_modules/.pnpm/node_modules. Щоб вимкнути цей підйом, встановіть hoist у false.

OSZAR »