Pnpm: чем он так хорош?
Anastasia KotovaPnpm ("Performance npm") — это современная альтернатива пакетному менеджеру npm. Основная цель pnpm - улучшение производительности и оптимизация использования дискового пространства при работе с проектами.
Рассмотрим несколько аспектов pnpm, которые (спойлер) делают его весьма привлекательным.
Экономия дискового пространства
Одним из ключевых отличий pnpm является его подход к хранению пакетов.
Npm дублирует пакеты в каждой новой установке для каждого из ваших проектов. Pnpm же использует ссылочное хранение.
Это означает, что все пакеты хранятся в одном общем месте на вашем компьютере, а проекты получают доступ к ним через жесткие ссылки. Такой подход значительно экономит дисковое пространство и ускоряет процесс локальной установки зависимостей.
Безопасность зависимостей
Как работает в npm
В npm, начиная с 3 версии, при установке зависимостей для оптимизации дискового пространства используется подход с flattened dependency tree (выравнивание дерева зависимостей).
Сейчас в корне node-modules будут находиться не только пакеты, которые указаны в package.json, но и их зависимости. А это позволит разработчику потенциально обратиться к такому пакету в коде проекта.
Хороший пример приводится в статье "pnpm's strictness helps to avoid silly bugs".
Cоздайте пустой проект и выполните в нёмnpm install express --save. Дальше перейдите в папкуnode_modules, которая была создана, и выполните тамls -1. Вы получите примерно такой вывод:
accepts array-flatten content-disposition content-type cookie cookie-signature debug depd destroy ...
Как вы видите, даже если вы установили толькоexpress, в папкеnode_modulesдоступно гораздо больше пакетов. Node.js неважно, что находится в вашемpackage.jsonфайле, у вас будет доступ ко всем пакетам, которые находятся в корнеnode_modules. Таким образом, вы можете начать использовать все эти пакеты, даже не устанавливая их явно.
(И да, я проверила этот пример на npm 10.5.0 и оно так и работает)

Как работает в pnpm
Pnpm решает эту проблему по другому. При его использовании в корне node_modules будут лежать только те пакеты, которые указаны в package.json. Благодаря механизму символических ссылок все вложенные зависимости для пакетов будут изолированы и недоступны для использования в вашем проекте напрямую.
Пример с express
Если мы возьмем тот же самым пример с express, но используем pnpm вместо npm то увидим следующее.

В корне node_modules будет лежать симлинк на конкретную версию библиотеки, установленную в папке node_modules/.pnpm
И далее уже в папке библиотеки express в node_modules будут лежать симлинки на все её зависимости.

Таким образом, больше не нужно использовать подход выравнивания дерева зависимостей и поднимать все пакеты в корень node_modules, как это сделано в npm, потому что вся нужная иерархия зависимостей организована с помощью символических ссылок.
Обратная совместимость с npm
Изначально pnpm позиционировался как полностью совместимый по CLI с npm, однако на данный момент уже существуют некоторые различия (например, добавление нового пакета через pnpm add вместо npm install).
Однако по-прежнему, миграция с npm на pnpm проходит не так сложно. Лично мне потребовалось выполнить команду pnpm import, модифицировать файл .npmrc, переустановить зависимости с помощью pnpm и исправить пару ошибок в проекте, которые появились в результате правильного резолвинга всех используемых зависимостей и их версий (привет пункту "Безопасность зависимостей").
Выводы
Я рассмотрела только основные ключевые особенности pnpm. Но уже по ним могу сказать, что pnpm выглядит как недооцененное, но крайне перспективное решение в мире пакетных менеджеров. И я бы рекомендовала использовать pnpm во всех проектах по умолчанию.
Полезные ресурсы
Интересный доклад с Holy.js про npm, pnpm и yarn
Сравнение с npm, на сайте pnpm
Подробное описание структуры node_modules при работе с pnpm, на сайте pnpm
Ответ на вопрос, почему не использовать симлинки вместо жестких ссылок, на сайте pnpm