Стоит ли переходить с npm на pnpm?
Вы наверняка встречали упоминания pnpm в конфигурациях монорепозиториев, CI и документации фреймворков. Возможно, кто-то из коллег его настойчиво рекомендует. Но стоит ли переход того трения, которое он привнесёт в вашу повседневную фронтенд-работу, или это решение проблем, которых у вас пока нет?
Вот что вам действительно нужно знать.
Ключевые тезисы
- pnpm использует content-addressable хранилище с hard links и symlinks, устраняя phantom dependencies и сокращая использование диска при работе с несколькими проектами.
- pnpm 11 продолжает ограничения lifecycle-скриптов, введённые в pnpm 10, требуя явного одобрения через
pnpm approve-buildsдля снижения рисков атак на цепочку поставок. - Фильтрация workspaces и протокол
workspace:*делают pnpm отличным выбором для монорепозиториев на Turborepo или Nx. - Закрепляйте версию пакетного менеджера через поле
packageManagerвpackage.jsonи используйте--frozen-lockfileв CI для детерминированных установок. - pnpm раскрывает свой потенциал в монорепозиториях и multi-project конфигурациях; для приложения с одним пакетом часто вполне достаточно npm.
Чем pnpm отличается от npm
pnpm — это не просто более быстрый npm. Настоящие отличия носят структурный характер.
npm создаёт плоскую директорию node_modules, из-за чего ваш код может случайно импортировать пакеты, которые вы никогда не объявляли как зависимости — эта проблема называется phantom dependencies. pnpm использует content-addressable хранилище с hard links и symlinks, поэтому на корневом уровне доступны только объявленные вами зависимости. Это делает разрешение зависимостей строже и более воспроизводимым.
Другое важное отличие — использование диска. pnpm хранит каждую версию пакета один раз глобально и связывает её жёсткими ссылками с вашими проектами. Если вы локально поддерживаете несколько Next.js или Vite проектов, вы не дублируете сотни мегабайт для каждого из них.
Для более глубокого разбора модели хранения и изоляции зависимостей стоит пробежаться по официальному сравнению pnpm и npm.
pnpm 11 и сдвиг в сторону безопасности
pnpm 11, выпущенный в апреле 2026 года, продолжает тенденцию, которая нарастала в последних мажорных версиях: приоритет безопасности и детерминированности над чистой скоростью.
Самое важное поведение, которое нужно знать перед переходом: pnpm теперь по умолчанию блокирует lifecycle-скрипты зависимостей, если они не были явно одобрены. Это рабочий процесс pnpm approve-builds, представленный в pnpm 10. Если вы устанавливаете пакет со скриптом postinstall — это типично для пакетов, компилирующих нативные бинарные файлы, таких как sharp, esbuild или canvas, — установка пройдёт успешно, но скрипт не выполнится, пока вы его не одобрите.
Это удивляет разработчиков, ожидающих, что всё просто заработает. Запустите pnpm approve-builds в интерактивном режиме или сконфигурируйте разрешённые build-зависимости в pnpm-workspace.yaml:
onlyBuiltDependencies:
- sharp
- esbuild
Это намеренный компромисс: больше трения на старте — меньше неприятных сюрпризов с цепочкой поставок в дальнейшем.
Workspaces и инструменты для монорепозиториев
Здесь pnpm заметно вырывается вперёд. npm workspaces работают, но реализация workspaces в pnpm более эргономична для крупных проектов.
Пакеты определяются в файле pnpm-workspace.yaml:
packages:
- 'apps/*'
- 'packages/*'
Из коробки вы получаете мощную фильтрацию:
pnpm --filter @myapp/ui build
pnpm --filter "...^@myapp/ui" test # run tests in packages that depend on ui
Для команд, использующих Turborepo или Nx, workspace-протокол pnpm (workspace:*) интегрируется без проблем и сохраняет внутренние зависимости явными.
Discover how at OpenReplay.com.
Закрепление версий через поле packageManager
Один практический шаг — независимо от того, используете ли вы Corepack: добавьте поле packageManager в package.json, чтобы указать, какой пакетный менеджер и какую версию ожидает ваш проект.
{
"packageManager": "pnpm@11.0.0"
}
Corepack может принудительно применять это в средах, где он включён, но даже без Corepack это чётко сообщает о намерениях вашей команде и настройкам CI.
Интеграция с CI на GitHub Actions
- uses: pnpm/action-setup@v6
with:
version: 11
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
Всегда используйте --frozen-lockfile в CI. Это предотвращает скрытые мутации lockfile и делает установки детерминированными.
Официальная документация по CI для pnpm также содержит примеры для GitHub Actions, GitLab CI, CircleCI, Azure Pipelines и Bitbucket Pipelines.
Когда переход оправдан
pnpm имеет наибольший смысл, если вы работаете в монорепозитории, управляете множеством локальных проектов или хотите более строгую изоляцию зависимостей по умолчанию. Модель безопасности pnpm approve-builds действительно полезна для команд, заботящихся о гигиене цепочки поставок.
Если вы поддерживаете приложение из одного пакета и npm вас устраивает, трения при миграции, скорее всего, не стоят затраченных усилий. npm workspaces достаточно зрелые для простых конфигураций, а статус дефолта экосистемы по-прежнему имеет реальную ценность.
Заключение
Честный ответ: сначала попробуйте pnpm на новом проекте. Набор команд практически идентичен, lockfile читаем, а большинство фронтенд-фреймворков — включая Next.js, Vite и Astro — поддерживают его без дополнительной конфигурации. Если строгость и экономия дискового пространства впишутся в ваш рабочий процесс, масштабирование на существующие проекты станет гораздо более простым решением.
Часто задаваемые вопросы
Обычно да. Удалите node_modules и package-lock.json, затем запустите pnpm import для конвертации lockfile, после чего выполните pnpm install. Следите за phantom dependencies, на которые мог полагаться ваш код в условиях плоской структуры npm — pnpm выявит их как недостающие импорты, и вы исправите это, явно добавив их в package.json.
approve-builds — это allowlist пакетов, которым разрешено запускать lifecycle-скрипты. Вы можете полностью отключить эту проверку, но это вернёт риски для цепочки поставок, которые pnpm 11 призван смягчить. Рекомендуемый путь — одобрять только те пакеты, которым вы доверяете и которым действительно нужны postinstall-шаги, например, компиляторы нативных бинарников.
Подавляющее большинство работает без изменений. Проблемы возникают в основном с пакетами, которые предполагают плоскую структуру node_modules или полагаются на phantom dependencies. Большинство популярных библиотек давно это исправили. Если что-то ломается, настройка public-hoist-pattern в .npmrc может воспроизвести npm-стиль hoisting для конкретных пакетов как обходной путь.
Для cold-установок pnpm обычно быстрее благодаря параллельному разрешению зависимостей и content-addressable хранилищу. Для warm-установок в проектах с общими зависимостями разница драматична, поскольку pnpm переиспользует уже загруженные пакеты через hard links. В CI с заполненным кэшем разрыв сужается, но pnpm в целом сохраняет преимущество.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.