Дайджесты новостей
Архитектурная иллюстрация режима loaded в pnpm: загрузка пакетов напрямую из хранилища в память Node.js в обход дерева симлинков.

Релизы pnpm 12.10.0 и 11.28.5: экспериментальный loaded-линкер, фиксация настроек в lockfile и патчи безопасности

Пакетный менеджер pnpm завоевал признание благодаря архитектуре контентно-адресуемого хранилища (Content-Addressable Store, CAS). Вместо копирования сотен мегабайт идентичных файлов pnpm сохраняет пакеты на диске в единственном экземпляре, собирая дерево зависимостей node_modules через жесткие ссылки и симлинки. Однако на масштабе крупных монорепозиториев эта схема упирается в ограничения файловых систем.

При десятках тысяч зависимостей генерация разветвленного леса симлинков создает ощутимую нагрузку на метаданные диска. В контейнерах Docker, на сетевых хранилищах NFS и в Windows NTFS этап связывания файлов может отнимать до трети времени развертывания проекта в CI.

Синхронный выпуск pnpm 12.10.0 и патч-релиза ветки 11.28.5 решает эту проблему ввода-вывода и закрывает несколько векторов уязвимостей.

Режим loaded: разрешение зависимостей без симлинков

Ключевое новшество релиза — экспериментальный компоновщик nodeLinker: { type: loaded }. В этом режиме pnpm полностью отказывается от создания физических симлинков в папке node_modules.

Вместо манипуляций с файловой структурой менеджер генерирует манифест .store-manifest.json и файл хуков загрузчика .store-loader.mjs. Разрешение модулей переносится в память процесса Node.js: рантайм считывает зарегистрированный лоадер и подгружает пакеты напрямую из глобального хранилища CAS.

Для модулей со скомпилированными бинарниками C++ или нестандартным чтением путей через __dirname предусмотрена директива excluded, возвращающая выбранные пакеты к классическому связыванию:

# .npmrc / pnpm-workspace.yaml — активация loaded-линкера и параметров надежности
node-linker:
  type: loaded
  # Изоляция нативных пакетов для совместимости с FFI
  excluded:
    - '@swc/core'
    - 'better-sqlite3'

# Сохранение правил дедупликации в манифесте блокировок для стабильности CI
lockfile:
  include-resolution-settings: true

Воспроизводимость сборок на серверах интеграции

Второй фокус обновления — опция lockfile.includeResolutionSettings: true. Ранее параметры дедупликации зависимостей (autoDedupe, dedupePeerDependents) считывались только из пользовательского файла .npmrc.

Если разработчик настраивал локальную дедупликацию, генерировал lockfile и отправлял коммит, пайплайн CI в облаке мог упасть: команда pnpm install --frozen-lockfile на чистом сервере видела расхождение в графе из-за отсутствия локальных флагов. Включение опции сохраняет точные правила разрешения конфликтов версий непосредственно внутри pnpm-lock.yaml, гарантируя идентичный результат на любой машине.

Установка и запуск проектов с новым линкером выполняются привычным набором команд:

# Проверка и установка зависимостей в проекте с новым линкером
# 1. Быстрая установка зависимостей без создания физических симлинков
pnpm install

# 2. Запуск приложения с подключением сгенерированного загрузчика Node.js
node --import ./node_modules/.store-loader.mjs index.mjs

# 3. Верификация графа зависимостей на сервере непрерывной интеграции
pnpm install --frozen-lockfile

Защита от вредоносных архивов и обхода путей

Релизы также закрывают важные угрозы безопасности:

  • Блокировка Path Traversal: устранена уязвимость, при которой пакет мог содержать относительные симлинки, позволяющие выйти за пределы хранилища pnpm и получить доступ к файлам хоста.
  • Лимит распаковки 64 МиБ: жесткое ограничение на объем метаданных распаковываемых архивов блокирует атаки класса «декомпрессионная бомба» (zip bomb), вызывавшие переполнение памяти.
  • Изоляция метаданных v12: сетевой кэш ответов реестра перенесен в изолированный каталог <cache-dir>/v12/ для исключения коллизий версий.

Практические выводы

Режим loaded node linker демонстрирует новый вектор развития экосистемы Node.js: перенос логики разрешения модулей из файловой системы в виртуальные рантайм-хуки. В отличие от жесткого подхода Yarn PnP, pnpm сохраняет возможность точечного исключения нативных библиотек через excluded, обеспечивая гладкую миграцию.

Командам крупных монорепозиториев имеет смысл протестировать режим loaded и активировать lockfile.includeResolutionSettings: true для устранения нестабильных падений сборок на серверах CI.