Прямой ответ
node_modules разрастается из-за архитектуры npm: каждый проект получает полную копию всех зависимостей и транзитивных пакетов — 300–800 МБ на проект это норма, десяток проектов — 5–8 ГБ только рабочих копий, плюс общий кэш npm (ещё гигабайты). Три действия приводят диск в порядок: чистка кэша (npm cache clean --force — безопасно, кэш восстановим), удаление node_modules заброшенных проектов (восстанавливаются одним npm ci), переход новых проектов на pnpm — он хранит каждый пакет на диске один раз и связывает проекты жёсткими ссылками, экономя 50–70% места.
Почему так много: анатомия node_modules
Пакетов в современном фронтенд-проекте сотни: фреймворк, сборщик, линтеры, типы, утилиты — и у каждого свои зависимости, иногда дублирующиеся в разных версиях (знаменитые «left-pad-эффекты»). Быстрая оценка:
du -sh node_modules # размер
npx npq audit # или npm audit — заодно безопасность
ls node_modules | wc -l # число пакетов верхнего уровня
Отдельная статья — вложенные node_modules внутри пакетов: там живут конфликтующие версии. Смотреть, кто кого притянул: npm ls <пакет>.
Кэши: где ещё лежат гигабайты
| Что | Где | Очистка |
|---|---|---|
| Кэш npm | ~/.npm |
npm cache clean --force |
| Кэш yarn | ~/.cache/yarn / %LOCALAPPDATA%\Yarn\Cache |
yarn cache clean |
| Store pnpm | ~/.local/share/pnpm/store |
pnpm store prune (удаляет только неиспользуемое!) |
| Кэши сборки | node_modules/.cache, .next, dist |
безопасно удалять, пересоздаются |
| Глобальные пакеты | npm ls -g --depth=0 |
удалить неиспользуемые CLI |
Важно: кэш npm — не мусор, а ускоритель повторных установок; чистить стоит при дефиците места, понимая, что следующая установка станет медленнее. Магазин pnpm чистится умнее — pnpm store prune убирает только пакеты, на которые нет ссылок из проектов.
pnpm: экономия без компромиссов
pnpm хранит все версии пакетов в одном контент-адресуемом магазине, а в проекты линкует их жёсткими ссылками:
- диск: 10 проектов с общим стеком занимают место ~одного проекта;
- скорость: установка из магазина — копирование метаданных, а не файлов;
- строгость: пакеты, не объявленные в
package.json, недоступны (npm это позволяет — источник «works on my machine»).
Миграция проекта: удалить node_modules и lock-файл npm, pnpm import (конвертирует package-lock), затем pnpm install. В монорепозиториях pnpm-workspace — стандарт де-факто; про особенности больших репозиториев — в статье про Git-монорепозитории.
Гигиена проектов: привычки, экономящие гигабайты
- Заброшенное — удалять:
node_modulesвосстанавливаетсяnpm ciза минуты; держать копию «на всякий случай» смысла нет. - Холодные проекты — архивировать без зависимостей: git-репозиторий + lock-файл весят мегабайты.
- Аудит дублей:
npm dedupeсхлопывает совместимые версии;npx depcheckнаходит неиспользуемые зависимости — минус место и поверхность атак. - Версии Node через менеджер (nvm/fnm/volta): несколько версий Node нужны, но каждая — это сотни МБ; оставляйте LTS и одну legacy.
- Windows-специфика: длинные пути в
node_modulesисторически ломали архиваторы и антивирусы — включите Long Paths и добавьте папки проектов в исключения Defender (ускоряет и установку, и сборку).
Связка с IDE и диском
node_modules — это ещё и десятки тысяч файлов, которые пытаются индексировать редакторы: исключения watcher/поиска для node_modules, dist, .next обязательны — как их выставить, описано в статье про языковые серверы VS Code. На стороне диска правило общее для всех экосистем (Python-окружения, Docker-образы, кэши сборки): SSD с 15–20% свободного места; при переполнении накопитель деградирует по скорости записи, и «тормозит всё» — соседняя экосистема Python разбирается в материале про venv/conda/uv.
Экспресс-аудит диска: найти гигабайты за пять минут
Порядок действий, когда «место кончилось, а что заняло — непонятно»:
- Найти все копии зависимостей по проектам:
# Linux/macOS (из корня с проектами):
find . -maxdepth 3 -type d -name node_modules -prune \
-exec du -sh {} + | sort -h
На Windows в PowerShell: Get-ChildItem -Recurse -Directory -Filter node_modules -Depth 3 | ForEach-Object { "{0}t{1:N0} МБ" -f $.FullName, ((Get-ChildItem $.FullName -Recurse -File | Measure-Object Length -Sum).Sum/1MB) }` — дольше, но показывает то же.
- Отсортировать и решить по каждому: активный проект — оставить; заброшенный — удалить каталог; холодный — удалить, lock-файл сохранит восстанавливаемость.
- Проверить общий кэш (
npm cache verifyпокажет размер) и кэши сборок в активных проектах. - Перевести самый тяжёлый активный проект на pnpm — на типовом стеке Next.js/Vite это минус 40–60% занимаемого места уже на первом проекте.
- Зафиксировать привычку: раз в месяц — повтор шага 1; занимает минуту и предотвращает «внезапные» 20 ГБ.
Важный нюанс SSD: удаление десятков гигабайт мелких файлов возвращает место не мгновенно — накопителю нужно время на TRIM/сборку мусора, и скорость записи восстановится в течение часов. Не паникуйте, если «удалил 10 ГБ, а диск всё ещё тормозит» — дайте ему поработать в покое.
FAQ
Безопасно ли удалять node_modules?
Да: это восстанавливаемая производная от package.json + lock-файла. Команда восстановления — npm ci (или pnpm install), она ставит ровно версии из lock-файла.
Почему npm ci лучше npm install для восстановления?
npm ci ставит строго по lock-файлу и удаляет существующий node_modules — результат воспроизводим; npm install может обновить lock-файл «на ходу».
Поможет ли перенос node_modules на другой диск? Технически возможно (симлинки), но ломает часть тулинга и замедляет сборку при медленном диске. Эффективнее pnpm: он решает ту же задачу штатно.
Стоит ли коммитить node_modules в git?
Никогда: это сотни МБ производных данных, конфликты в lock-мерах и нагрузка на репозиторий. В git — только package.json и lock-файл.
Ускорит ли pnpm установку, если SSD медленный? Да, и заметно: магазин pnpm исключает повторное скачивание и распаковку одних и тех же пакетов, а линковка жёсткими ссылками создаёт меньше файловых операций, чем копирование npm. На SATA-SSD выигрыш меньше, чем на NVMe, но остаётся существенным.
Почему после чистки кэша установка стала медленнее? Это ожидаемо: кэш пуст, пакеты скачиваются заново. Разовая цена за свободное место; вторая и последующие установки снова пойдут быстро. Не чистите кэш «профилактически» чаще, чем требует дефицит диска.
Источники: документация npm (cache, ci), мотивация pnpm, документация Node.js (ссылки в шапке).