Pnpm - менеджер пакетов для Node.js. Ранее я писал статью о том, зачем нам использовать pnpm. В этой статье я хочу продемонстрировать, как использование pnpm помогает предотвратить некоторые глупые ошибки.

При использовании npm у вас есть доступ к пакетам, на которые вы не ссылаетесь в package.json вашего проекта. Это возможно, потому что npm создает плоскую папку node_modules.

Поясню это на примере.

  • создать пустой проект: mkdir project && npm init -y
  • запустить npm install express --save
  • перейдите в созданную папку node_modules
  • запустить ls -1

Вы получите результат, похожий на этот:

accepts
array-flatten
content-disposition
content-type
cookie
cookie-signature
debug
depd
destroy
ee-first
encodeurl
escape-html
etag
express
finalhandler
forwarded
fresh
http-errors
inherits
ipaddr.js
media-typer
merge-descriptors
methods
mime
mime-db
mime-types
ms
negotiator
on-finished
parseurl
path-to-regexp
proxy-addr
qs
range-parser
send
serve-static
setprototypeof
statuses
type-is
unpipe
utils-merge
vary

Как видите, несмотря на то, что вы установили только express, в папке node_modules доступно гораздо больше пакетов. Node.js не волнует, что находится в вашем package.json файле, у вас будет доступ ко всем пакетам, которые находятся в корне node_modules. Таким образом, вы можете начать использовать все эти пакеты, даже не устанавливая их явно.

Допустим, вам нужно debug в вашем проекте. Вы можете начать использовать его и забыть добавить его в package.json. Ваш проект будет работать нормально. Вы зафиксируете свои изменения и опубликуете их в рабочей среде. Он будет хорошо работать даже в продакшене. Однако через несколько недель или месяцев с большой вероятностью может произойти одно из двух:

  1. может быть опубликована новая основная версия debug с новым API. Ваш код был написан для debug@1, и он нуждается в некоторых обновлениях для работы с debug@2. Вы в безопасности, пока express не использует debug@1, потому что debug@1 установлен в корень node_modules. Однако express может обновить свою зависимость в любой момент, исправить все случаи использования debug и опубликовать новый патч (патч, потому что express не содержал критических изменений). В следующий раз, когда вы сделаете npm install, express будет обновлен и debug@2 установлен в корень вашего node_modules. Проект сломается, даже если вы не внесли никаких изменений!
  2. другая возможность состоит в том, что express перестает использовать debug. Он может просто удалить его из зависимостей и опубликовать новую версию. Когда вы обновите express, ваш код сломается, потому что пакета debug больше не будет node_modules.

Теперь представьте, что ваш проект - это не веб-приложение, а пакет, который используют многие другие люди. Если вы не включите пакет, используемый в коде, в package.json, ваш пакет станет бомбой с таймером. Вы помните левую клавиатуру? Я могу представить себе подобную катастрофу в будущем из-за забытой зависимости.

Как pnpm помогает избежать подобных ошибок?

В отличие от npm, pnpm не пытается переместить все в корень node_modules. Если вы удалите папку node_modules, созданную npm в предыдущем примере, и запустите pnpm install express, вы увидите, что ls -1 напечатает только одну символическую ссылку в папке node_modules: express. Нет debug!

При следующем запуске ваше приложение немедленно выйдет из строя, потому что не сможет найти debug. Так и должно быть! Чтобы исправить проект, вы просто запустите pnpm install debug, и debug будет добавлен в ваш package.json (pnpm по умолчанию сохраняет пакеты в package.json, даже если параметр --save не передан). Имея debug в вашем package.json, вы можете быть уверены, что он всегда будет установлен в node_modules и будет работать с вашим кодом, как и ожидалось.

В pnpm возникает множество проблем, потому что некоторые пакеты / инструменты не работают. Эти проблемы в основном возникают из-за того, что пакеты / инструменты имеют package.json, в которых отсутствуют зависимости. Некоторые разработчики даже думают, что не включать зависимости в package.json - это нормально, потому что «это работает с npm / yarn». Это не нормально! Это может сработать сегодня, но сломается завтра.

Вы можете не использовать pnpm. Но, пожалуйста, публикуйте действующие пакеты. Если вы не используете pnpm, воспользуйтесь инструментами вроде dependency-check, чтобы проверить свой пакет перед его публикацией в реестре.

установка глобального стиля npm

Спустя месяц после публикации этой статьи я обнаружил, что подобных ошибок можно избежать и с помощью npm! Это не поведение по умолчанию, но npm может установить node_modules в другом макете, в котором

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

Для этого просто запустите npm с опцией --global-style или измените ее значение в конфигах через npm c set global-style true.

Хотите попробовать pnpm?

Просто установите pnpm через npm: npm install -g pnpm. И используйте его вместо npm, когда хотите что-то установить: pnpm i foo.

Также вы можете прочитать дополнительную информацию в pnpm GitHub repo или pnpm.js.org. Вы можете подписаться на pnpm в Твиттере или обратиться за помощью в pnpm Gitter Chat Room.

(Эта статья изначально была размещена на https://www.kochan.io/nodejs/pnpms-strictness-helps-to-avoid-silly-bugs.html)