Познакомьтесь с этим малоизвестным менеджером пакетов JavaScript

Pnpm - это менеджер пакетов для JavaScript, например npm и yarn. Я лично считаю, что pnpm менее известен, чем следовало бы. Согласно README в репозитории pnpm составляет:

• Быстро. Так же быстро, как npm и Yarn.

• Эффективный. Одна версия пакета сохраняется на диске только один раз.

Отлично для монорепозитория.

• Строгий. Пакет может получить доступ только к тем зависимостям, которые указаны в его package.json.

• Детерминированный. Имеет файл блокировки с именем pnpm-lock.yaml.

• Работает везде. Работает в Windows, Linux и OS X.

В этой статье я делюсь некоторыми из моих уроков, полученных при миграции монорепозитория (под управлением Yarn workspace + Lerna), содержащего более 60 пакетов, на pnpm. Чтобы понять, почему pnpm может быть хорошим решением для вашего проекта, давайте начнем с викторины.

Контрольный опрос

Представьте, что вы начинаете новый проект JavaScript. Как и большинство людей, вы устанавливаете свои зависимости с помощью npm или Yarn. В этом примере воспользуемся npm . Вашему проекту нужен Express, поэтому вы должны:

npm install -g express

Установлены зависимости!

Допустим, в Express есть пакет зависимостей debug.

Как сейчас ваш node_modules?

Попробуйте подумать об этом несколько секунд ...

.

.

.

.

.

Выполнено?

Если вы ответили A, вы, вероятно, думаете, что именно так и должны работать зависимости.

Но если вы попробуете это с npm или Yarn, вы обнаружите, что на самом деле ответ - B, и это проблема.

Почему это проблема?

Благодаря структуре, показанной на B, наш код теперь может require('debug'), даже если мы не зависим от него явно в нашем package.json.

Подумайте, что будет, если:

  1. Express обновляет их debug зависимость критическими изменениями.
  2. Экспресс решил больше не зависеть от debug.

В обоих случаях наш код завершится ошибкой, потому что он неявно зависит от debug.

В правильной структуре наш код никогда не будет иметь доступа к debug. Это связано с тем, как Node.js находит содержимое внутри node_modules.

Почему npm решил сделать это тогда?

npm фактически реализовал структуру A выше до npm3, но с ней были некоторые проблемы.

Дубликаты

Если мы добавим debug в качестве зависимости нашего проекта, у нас может быть две разные копии debug.

Проблемы с этим:

  • Дубликаты на нашем диске
  • Возможные дубликаты в наших комплектах
  • Некоторые пакеты ломаются при наличии дубликатов (например, React)

Каталоги с длинной вложенностью

Некоторые операционные системы плохо справляются с длинными каталогами.

Начиная с версии 3, npm начал использовать уплощенный node_modules. Подробнее об этом можно прочитать здесь.

Почему это проблема? (Продолжение)

Мы уже установили, что наличие неявных зависимостей не идеально. Если вы работаете с большим монорепозиторием, тогда проблема еще хуже. Будет труднее отследить, откуда взялись фактические зависимости, которые использует проект.

Дублирование также является проблемой. Хотя Yarn выполняет подъемы для оптимизации использования дискового пространства, в некоторых случаях он неожиданно дает сбой.

Как pnpm решает эти проблемы

pnpm использует жесткие ссылки и символические ссылки для достижения полустрогой node_modules структуры, а также для того, чтобы на диске всегда сохранялась только одна версия модуля.

Допустим, мы выполняем pnpm install express в нашем проекте. Вот как выглядит наш node_modules:

Обратите внимание, что наш код не имеет доступа к debug, потому что он не находится непосредственно в корневом node_modules каталоге.

pnpm создает специальный .pnpm каталог, содержащий жесткие ссылки всех модулей. В разделе express/4.0.0 находится модуль express, который является жесткой ссылкой на глобальный pnpm-store, и символическая ссылка debug на жесткую ссылку debug, которая также ссылается на глобальный pnpm-store.

Глобальный pnpm-store имеет примерно аналогичную структуру. Фактический пакет, который мы устанавливаем с помощью pnpm, хранится здесь. Обычно он сохраняется под ~/.pnpm-store.

Да, работает ли он с каждым пакетом в реестре npm?

К сожалению, если вы переходите с Yarn / npm на pnpm, некоторые пакеты могут не работать. В большинстве случаев это вызвано отсутствием зависимостей в package.json файле пакета.

Например, возьмем antd-table-infinity. Пакет не имеет зависимостей от antd, но имеет некоторый код, который импортирует из antd. Пакет также не связывается antd с ним перед публикацией. В большинстве случаев, когда вы используете этот пакет, у вас, вероятно, уже установлено antd. Затем уплощенная структура node_modules позволяет этому пакету находить antd. При использовании pnpm этот пакет больше не сможет находить antd и завершится ошибкой.

К счастью, pnpm предоставляет ловушки, так что мы можем решить эту проблему на нашей стороне. Мы можем вручную добавить antd как antd-table-infinity’s peerDependency с помощью этого простого крючка.

Какую пользу нам приносит pnpm?

На мой взгляд, двумя основными преимуществами pnpm являются:

Никаких дубликатов

  • На вашем компьютере может быть только одна версия пакета
  • Экономит место на диске, независимо от того, сколько JS-проектов у вас на компьютере
  • Больше никаких проблем с дублированием React

Строгий

  • Отсутствие случайного доступа к не зависимым объектам
  • Более стабильный, более последовательный и более предсказуемый
  • Избегайте глупых ошибок

Отсутствие дубликатов означает, что независимо от того, сколько проектов на вашем компьютере зависит, скажем, от Electron, на вашем компьютере будет существовать только одна копия каждой версии Electron. Также отлично работает для монорепозиториев. Отсутствие дубликатов помогает уменьшить размер монорепозитория на диске. Строгость помогает раньше выявлять трудные для понимания ошибки.

Если вы переносите проект с npm или Yarn на pnpm, скорее всего, вы обнаружите unable to resolve module "some-module" ошибку. Ваш проект мог работать раньше из-за уплощенной node_modules структуры, но потерпит неудачу при более строгой структуре - это хорошо, если вы нацелены на долгосрочную ремонтопригодность!

Резюме

Подводя итог, pnpm является строгим и помогает нам экономить место на диске. Строгость делает вещи более предсказуемыми и раньше выявляет ошибки. Вам решать, насколько это важно. Если вы работаете с крупномасштабным монорепозиторием, я настоятельно рекомендую проверить pnpm.

Эта статья охватывает лишь часть того, что может предложить pnpm. Надеюсь, вы сочтете это полезным! Дополнительные ресурсы о pnpm можно найти ниже. Если вы еще не прочитали их, оно того стоит.

Ресурсы: