Кратко: экономия диска с pnpm достигается за счёт общего хранилища пакетов, жёстких ссылок и строгого lockfile — это режет дубли и ускоряет инсталляции. Подробный вводный обзор — Оптимизация дискового пространства: как pnpm помогает сократить размер node_modules в 2026 году, а ниже — разбор механики, настроек и подводных камней с примерами для монорепо, CI и контейнеров.
Там, где node_modules превращался в бесконечный чердак с одинаковыми коробками, pnpm вводит порядок кладовщика: каждый уникальный пакет хранится один раз, а рабочие проекты берут его через ссылки. Диск перестаёт таять на глазах, кэш обретает смысл, а пересборки не выглядят как капитальный ремонт.
Смена менеджера пакетов редко бывает романтичной, но именно здесь замена инструмента меняет экономику: меньше гигабайтов, ниже сетевые издержки, стабильнее сборки. И за этой сухой бытовой выгодой — чёткий инженерный замысел, где вычислительная дисциплина соседствует с радикально бережным отношением к байтам.
Почему node_modules разрастается и как pnpm меняет правила
Корень проблемы — дублирование зависимостей и хаотичное дублирование версий; решение pnpm — общий контент-адресуемый store и ссылки вместо копий. Размер падает, а целостность графа зависимостей становится предсказуемой.
Традиционный подход к установке пакетов сводится к копированию каждой зависимости прямо в папку проекта. Каждая новая версия — новый набор файлов, каждая вариация графа — очередной клон. В больших экосистемах, особенно при множестве сервисов, это приводит к каскаду однотипных копий, которые отличный кандидат на дедупликацию, но менеджеры прошлого поколения не преследовали эту цель радикально. pnpm строит установку иначе: формирует единый контент-адресуемый store на машине и кладёт в него каждый уникальный артефакт ровно один раз. В каталоге проекта оказывается не гора файлов, а лёгкая прослойка ссылок, указывающих на общий оригинал. Эта архитектура режет размер каталога проекта кратно, сохраняя при этом привычную семантику импорта модулей и изоляцию зависимостей на уровне графа.
Парадоксально, но строгость даёт свободу. Жёсткие ссылки и «виртуальный» store приучают систему к неизменяемости артефактов, а это снижает вероятность «тихой» порчи кэша. Lockfile отражает точную, а не приблизительную конфигурацию. В итоге пространство перестаёт быть жертвой компромиссов, а время установки всё чаще упирается не в сеть, а в файловую систему и CPU при постинсталляционных скриптах.
Что именно копируют npm и yarn, и что оставляет pnpm
npm и классический yarn копируют файлы пакетов в проект, pnpm — оставляет в проекте ссылки на файлы из общего хранилища. Экономится место и время на распаковку, а общедоступный кэш используется всеми проектами на машине.
В старых схемах каждый пакет — это набор файлов, который повторяется в каждом проекте, даже если контент совпадает байт-в-байт. Такой подход быстро разгоняет каталог node_modules до десятков гигабайт, особенно если команда ведёт монорепозиторий или парк микросервисов. У pnpm файлы не копируются повторно; вместо этого в проект кладутся жёсткие ссылки (или джанкшены на Windows), указывающие на единственный «источник правды» в store. В результате два проекта с одинаковым набором зависимостей не увеличат суммарный размер на диске вдвое: добавится только тонкая надстройка ссылок и метаданных.
Что происходит на диске: жёсткие ссылки, виртуальный store и где рождается экономия
Экономия рождается в общем store: каждый файл устанавливается один раз и раздаётся проектам через жёсткие ссылки. На совместимых файловых системах это даёт почти нулевую цену дубликатов, сохраняя привычные пути в node_modules.
pnpm создаёт контент-адресуемое хранилище — своего рода библиотеку, где каждая книга идентифицируется по содержимому, а не по месту на полке. Когда проект «просит» зависимость, он получает не копию книги, а карточку-указатель: жёсткую ссылку на тот же блок данных. Для файловых систем поддерживающих hard link, такие ссылки не занимают дополнительного места, а записывают лишь ещё один индекс к тем же данным на диске. В node_modules остаётся организованный фасад: привычные структуры директорий, корректные резолвы зависимостей, аккуратная изоляция peerDependencies. Такой фасад скрывает от разработчиков библиотечный механизм, но именно он возвращает гигабайты и уменьшает давление на систему ввода-вывода.
Где-то между элегантностью идеи и её приземлением живут детали. На Windows pnpm применяет джанкшены, на macOS и Linux — жёсткие ссылки и симлинки. На файловых системах с ограничениями по жёстким ссылкам используется деградация к копированию, но и там выигрыши заметны благодаря общему кэшу и строгой работе с lockfile. В контейнерах экономия усиливается: слои образов меньше, кэш CI-пайплайна стабильнее, пересборки предсказуемы. В конечном счёте, к механизму прирастают практики — и именно их сочетание делает экономию устойчивой.
| Механизм | Как экономит место | Совместимость | Ограничения |
|---|---|---|---|
| Жёсткие ссылки (hard links) | Один набор данных — множество путей | Linux, macOS (ext4, APFS, др.) | Нельзя ссылаться на разные ФС; счётчики ссылок |
| Симлинки/джанкшены | Тонкая прослойка вместо копий | Windows (NTFS), кросс-платформенно | Поведение в инструментах, чувствительных к путям |
| Контент-адресуемый store | Один раз скачано — переиспользуется повсюду | Все платформы | Требует дисциплины в lockfile и кэше |
Виртуальный store и «видимость» зависимостей
pnpm держит фактические пакеты вне node_modules, а внутрь выводит аккуратные ссылки и хелперы. Это сохраняет корректный алгоритм резолва и не даёт неявным зависимостям «просачиваться» наверх.
Такая архитектура дисциплинирует зависимости: модули не могут полагаться на соседей, если не объявили их явно. Бонусом становится предсказуемость сборки: если пакет не заявлен — он недоступен, даже если «живет рядом» в общем store. Разработчики получают ясный сигнал из сборки, а не молчаливую удачу на одной машине и падение на другой. Экономия диска здесь идёт рука об руку с прозрачностью графа.
Реальные выигрыши: монорепозитории, CI и контейнеры
Самые большие выгоды pnpm приносит там, где много проектов и повторяющихся зависимостей: монорепо, CI-пайплайны, контейнерные сборки. Экономится место, время и сетевой трафик.
В монорепозитории десятки пакетов часто делят между собой одни и те же библиотеки. В мире копий это лестница в небо: каждый пакет тащит свой багаж. pnpm прекращает эту экскурсию — общий store хранит багаж для всех, а рабочие каталоги лишь помечают, что именно им нужно. В CI, где чистые агенты изрядно тратят минуты на дублирующие загрузки, «тёплый» store вместе с pnpm fetch и детерминированным lockfile сокращает холодный старт и стабилизирует кэш. В контейнерах чуть иная магия: правильный порядок слоёв и вынесение store в отдельный слой позволяет слою с приложением быть тонким и переиспользуемым. Так и пространство освобождается, и сборки становятся повторяемыми, а не походят на попытку угадать погоду по кофейной гуще.
| Сценарий | Размер с npm/yarn | Размер с pnpm | Экономия | Комментарий |
|---|---|---|---|---|
| Монорепо, 40 пакетов | ~12–16 ГБ | ~4–6 ГБ | 60–70% | Общий store и единый lockfile |
| CI с кэшем зависимостей | ~2–3 ГБ на билд | ~0.5–1 ГБ на билд | 50–70% | pnpm fetch + кэш слоёв |
| Docker-образ сервиса | +600–900 МБ | +250–450 МБ | 40–60% | Выделенный слой с store |
Скорость установки и прогрев кэша
Установка с pnpm быстрее там, где кэш прогрет: распаковки меньше, сеть молчит, а диску достаётся работа по созданию ссылок. На «холодном» старте преимущество проявляется за счёт строгого lockfile и параллелизма.
Распаковка архивов — затратная операция. Когда она проводится один раз, а последующие инсталляции лишь создают ссылки, профит становится заметным даже на SSD. Параллельное скачивание, «сухая» команда pnpm fetch и режим --prefer-offline сдвигают бутылочное горлышко от сети к локальным операциям, а они предсказуемее и дешевле. В результате «прогретые» разработческие машины и CI-агенты ощутимо экономят минуты, которые прежде таяли в логах установщика.
Настройки pnpm, которые дают максимум экономии
Максимальная экономия достигается комбинацией общего store, строгого lockfile и осознанных флагов установки. Важны: frozen-lockfile, prefer-offline, pnpm fetch, грамотный кэш в CI и монорепо-конфигурация.
Архитектура pnpm уже экономит, но настройки превращают выгоду в гарантию. Жёсткое соблюдение lockfile отсекает «ползучие» апдейты, которые раздувают кэш. Режимы офлайна и предварительной закачки смещают сетевые риски в предсказуемую фазу, а workspace-конфигурация в монорепо собирает граф зависимостей в единое полотно. Раздельные каталоги для store и для проекта позволяют тонко управлять контейнерными слоями и артефактами кэша. Часть флагов стоит включать по умолчанию, часть — под конкретную стадию пайплайна.
pnpm fetch— заранее скачивает артефакты в store без установки; полезно в CI и Docker-слоях.pnpm install --frozen-lockfile— жёсткая фиксация графа; исключает неожиданные дубли и дрейф.--prefer-offline— берёт из кэша при любом удобном случае; сеть трогает реже.store-dirв .npmrc — явное место store для кэширования между сборками.pnpm prune— удаляет мёртвые артефакты; держит store в форме.node-linkerиpackage-import-method— тонкая настройка типа ссылок под ФС/CI.
| Флаг/настройка | Эффект | Когда включать | Побочный эффект |
|---|---|---|---|
--frozen-lockfile |
Детерминированные сборки | CI, релизы | Требует актуального lockfile |
--prefer-offline |
Меньше сетевых обращений | Локальная разработка, CI с кэшем | Редкий риск устаревшего кэша |
pnpm fetch |
Тонкий слой зависимостей в Docker | Контейнеры, многоэтапные сборки | Нужна корректная стадия кеша |
store-dir=... |
Шеринг кэша между сборками | CI-агенты, хост-машины | Нужны права/квоты на каталог |
Монорепо и workspaces: один lockfile — меньше копий
Единый lockfile для рабочих пространств предотвращает дрейф версий и повторную установку почти одинаковых деревьев. Экономия места и времени становится системной, а не случайной.
Workspaces позволяют собирать зависимый зоопарк пакетов в стройную композицию. Когда каждый пакет живёт своим lockfile, небольшие расхождения версий умножают артефакты. Единый lockfile и согласованные версии снимают эту нагрузку. В такой схеме pnpm не только делит файлы через store, но и предотвращает саму причину разрастания — несогласованность графа. Каждое обновление проходит через ревью, а у кэша появляется шанс на долгую спокойную жизнь.
Подводные камни и как их обходить без лишних копий
Переход на pnpm иногда вскрывает тонкие места: нестандартные postinstall-скрипты, завязки на физические пути, хрупкие peerDependencies. Решение — поправить скрипты, зафиксировать пира и следить за «side effects».
Многие инструменты «в поле» исходят из предположения, что файлы лежат там, где их положили ранее другие менеджеры. В мире ссылок такие предположения ломаются. Скрипты, читающие из относительных путей вне своего пакета, требуют корректировок. Некоторые сборочные цепочки берут зависимости «наугад», рассчитывая на транзитивную доступность — с pnpm подобная магия исчезает, и это, по сути, благо. Ещё одна особенность — кэш «side effects»: результаты сборок нативных модулей, которые стоит хранить и переиспользовать, но нужно держать в чистоте при смене платформ и ABI.
- Убрать обращения к путям вне пакета; использовать
require.resolveи API инструментов. - Явно объявлять peerDependencies и их версии; избегать плавающих значений.
- Проверить postinstall-скрипты на работу в read-only окружениях и в ссылочной структуре.
- Включить и обслуживать кэш side effects для нативных модулей на CI.
- Отладить поведение на Windows: джанкшены и права доступа могут повлиять на линтеры.
Когда симлинки мешают сборке и что делать
Редкие инструменты ошибочно трактуют симлинки как внешние источники и «выпадают» из оптимизаций. Решение — обновить инструментарий или поменять стратегию линковки в конфигурации pnpm.
Старые обфускаторы, устаревшие бандлеры, жёстко прописанные пути — всё это ещё встречается. При проблемах разумно протестировать альтернативные значения node-linker или переключить метод импорта пакетов. В большинстве современных цепочек сборки готовность к симлинкам уже норма, а проблемы решаются точечными обновлениями. Экономия места не стоит того, чтобы держаться за наследие, которое тратит минуты и гигабайты впустую.
Измеряем результат: методика, метрики, правдивые цифры
Корректная оценка выгоды строится на замерах «до/после»: размер node_modules и store, время установки на холодном/тёплом старте, размер контейнерных слоёв. Нужны воспроизводимые условия и фиксированный lockfile.
Любая оптимизация требует чисел. Простой сценарий: зафиксировать lockfile, очистить кэши и провести холодную установку, затем тёплую — с прогретым store. Замерить размеры каталогов node_modules, .pnpm-store и итоговых артефактов сборки. Для контейнеров — отдельно оценить слои после шага pnpm fetch и после установки. В CI добавить метки времени, чтобы понимать, где теряются минуты: в сети, распаковке или постинстале. Цифры показывают реальную экономию и подсказывают, где ещё есть воздух для улучшений.
- Зафиксировать lockfile и версии Node, отключить автообновления.
- Очистить кэш и удалить node_modules, сохранить снимок размеров диска.
- Провести холодную установку, замерить время и размер.
- Повторить установку с прогретым store, зафиксировать показатели.
- Собрать Docker-образ в два этапа: с
pnpm fetchи без; сравнить слои. - Собрать отчёт: проценты экономии, стабильность времени, отклонения.
| Метрика | Инструмент | Базовый ориентир | На что смотреть |
|---|---|---|---|
| Размер node_modules | du -sh, проводник |
Снижение в 2–4 раза | Стабильность между сборками |
| Размер store | du -sh ~/.pnpm-store |
Растёт умеренно | Удаление мёртвых пакетов (pnpm prune) |
| Время cold start | CI таймеры | Сокращение на 20–40% | Сети vs распаковка |
| Вес Docker-слоёв | docker history |
-200–400 МБ | Порядок команд в Dockerfile |
Как фиксировать успех и не потерять кэш
Успех виден там, где кэш живёт дольше одной сборки: lockfile стабилен, store доступен агентам, а пайплайн сохраняет артефакты между задачами. Тогда цифры перестают прыгать и становятся прогнозом.
Практика показывает, что даже хорошие оптимизации исчезают, если каждый билд начинается «с нуля». Сохранение store между джобами, разнос шагов fetch и install по разным слоям, аккуратные ключи кэширования, учитывающие и lockfile, и системные параметры — это дисциплина, которая монетизирует преимущества pnpm. Пара недостающих строк в конфигурации способна вернуть серые логи и распухшие каталоги. Стоит один раз выстроить пайплайн, чтобы дальше наблюдать лишь плановое старение зависимостей, а не хаос.
FAQ — ответы на вопросы, которые задают чаще всего
Сколько места на диске реально экономит pnpm на нескольких проектах?
На общей машине экономия достигает 50–70% благодаря общему store и жёстким ссылкам вместо копий. Чем больше совпадающих зависимостей, тем выше выигрыш.
Замеры в командах с десятками сервисов показывают, что каждый новый проект почти не увеличивает общий объём — добавляет только «обвязку» ссылок и новые артефакты, если появляются уникальные версии библиотек. Там, где раньше node_modules росли линейно с количеством проектов, с pnpm кривая сглаживается, а пространство возвращается владельцу машины без борьбы.
Будет ли pnpm быстрее npm/yarn на чистой установке с нуля?
На холодном старте преимущество умеренное и зависит от сети, но уже заметно за счёт параллельности и аккуратной распаковки. На тёплом старте выигрыши значительны.
Холодная установка всегда ограничена скоростью скачивания и распаковки архивов. Здесь pnpm играет в ту же игру, но делает меньше лишнего. Как только кэш прогревается, затраты переползают из «скачать и распаковать» в «сделать ссылки», и это кратно быстрее. Поэтому устойчивый эффект виден не на первом прогоне, а на последующих.
Совместим ли pnpm со всеми популярными инструментами сборки?
С большинством — да: современные бандлеры и тестовые раннеры корректно работают с симлинками и жёсткими ссылками. Проблемы встречаются у наследованных тулов.
При сбоях помогает обновление до последних версий, а также настройка node-linker и package-import-method. В редких случаях проще заменить проблемный инструмент, чем поддерживать поведение, рассчитанное на мир копий и прямых путей.
Что делать с нативными модулями и их «side effects» при использовании pnpm?
Включить кэш сайд-эффектов и отслеживать платформу/ABI при сборке. Тогда бинарные артефакты не будут пересобираться без повода и не распухнут в кэше.
Правильная конфигурация CI записывает кеш ключами, учитывающими версию Node, архитектуру и параметры компоновки. Это позволяет переиспользовать бинарники там, где это безопасно, и освежать их, когда среда меняется, избегая ложной экономии и повторных часовых сборок.
Как устроить оптимальный Dockerfile для pnpm, чтобы уменьшить размер образа?
Вынести pnpm fetch в ранний слой, кэшировать store, а установку и сборку делать позже. Тогда слой с зависимостями переиспользуется чаще и весит меньше.
Хороший паттерн: скопировать только lockfile и манифесты, выполнить pnpm fetch, затем добавить исходники и запустить pnpm install --offline. Порядок команд должен минимизировать перегенерацию слоя с кэшем при изменениях кода, чтобы тяжёлые артефакты не «съезжали» при каждом коммите.
Можно ли хранить общий store pnpm на отдельном разделе или в сети?
Да, store настраивается параметром store-dir, и его можно вынести в отдельный каталог, раздел или сетевую шару. Главное — совместимость ссылок и скорость.
Если файловая система или сетевое хранилище ограничивают жёсткие ссылки, pnpm упадёт в режим копирования или симлинков. Тогда выигрыши сохранятся не полностью, но общий кэш по-прежнему сэкономит трафик и время установки.
Финальный аккорд: экономия места как новая дисциплина инженерии
Экономия диска давно перестала быть «мелочью для энтузиастов». С pnpm она превращается в стратегию: порядок вместо хаоса, общий store вместо копий, детерминированность вместо случайности. Когда пространство и время в сборках складываются в предсказуемую линию, растёт не только скорость, но и надёжность разработки.
Технология даёт основу, а практика закрепляет результат. Дисциплина lockfile, методичная работа с кэшем, аккуратная настройка CI и контейнеров — всё это делает экономию не разовой акцией, а привычкой, которая возвращает ресурсы день за днём. И там, где вчера спорили о гигабайтах, завтра обсуждают архитектуру продукта, потому что инфраструктура больше не шумит.
How To: быстрый переход на pnpm с гарантированной экономией
Ниже — сжатая последовательность действий, которая помогает перенести проект на pnpm без сюрпризов и с предсказуемой выгодой в месте и времени.
- Включить pnpm через Corepack и зафиксировать версию в репозитории.
- Сгенерировать lockfile pnpm, проверить граф зависимостей и peerDependencies.
- Настроить
store-dirиpnpm fetchдля локалки, CI и Docker. - Перевести пайплайн на
--frozen-lockfile, сохранить и прогревать кэш. - Перебрать postinstall-скрипты, убрать привязки к физическим путям.
- Замерить «до/после»: размер node_modules, store, слоёв образа и время установки.
- Включить регулярный
pnpm pruneи ревью обновлений зависимостей.

