Back

Стоит ли переходить с npm на pnpm?

Стоит ли переходить с 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:*) интегрируется без проблем и сохраняет внутренние зависимости явными.

Закрепление версий через поле 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.

OpenReplay