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
. Ваш проект будет работать нормально. Вы зафиксируете свои изменения и опубликуете их в рабочей среде. Он будет хорошо работать даже в продакшене. Однако через несколько недель или месяцев с большой вероятностью может произойти одно из двух:
- может быть опубликована новая основная версия
debug
с новым API. Ваш код был написан дляdebug@1
, и он нуждается в некоторых обновлениях для работы сdebug@2
. Вы в безопасности, покаexpress
не используетdebug@1
, потому чтоdebug@1
установлен в кореньnode_modules
. Однакоexpress
может обновить свою зависимость в любой момент, исправить все случаи использованияdebug
и опубликовать новый патч (патч, потому чтоexpress
не содержал критических изменений). В следующий раз, когда вы сделаетеnpm install
,express
будет обновлен иdebug@2
установлен в корень вашегоnode_modules
. Проект сломается, даже если вы не внесли никаких изменений! - другая возможность состоит в том, что
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)