Чтобы выяснить, из-за чего установка Node-проекта занимает много места на macOS, измерьте размер установленных пакетов, а затем отследите самых крупных кандидатов по дереву зависимостей npm. В Терминале перейдите в каталог проекта: du показывает использование дискового пространства, npm ls выводит дерево установленных пакетов, а npm explain объясняет, почему пакет присутствует. Они отвечают на разные вопросы: размер указывает на то, что занимает место; цепочка зависимостей указывает на то, что привело к его установке.

Измерение установленных пакетов на macOS

Откройте Терминал, перейдите в папку проекта и убедитесь, что она содержит node_modules, прежде чем выполнять измерения. Следующие команды работают в стандартной для macOS оболочке zsh и не зависят от особенностей обработки подстановочных знаков шелла:

cd "/path/to/your/project"
ls -ld node_modules
find node_modules -mindepth 1 -maxdepth 1 -type d -prune -exec du -sh {} + | sort -h

du -sh выводит понятный человеку общий размер каждого непосредственного подкаталога, а sort -h упорядочивает эти значения по возрастанию. Смотрите снизу вверх, чтобы увидеть самые большие записи. Команда find измеряет каждый каталог верхнего уровня один раз: например, она сообщает о node_modules/@example как об одном объединенном каталоге области видимости (scope), а не о каждом пакете внутри него по отдельности. Это полезный первый шаг, а не отчет об индивидуальном вкладе каждой отдельной зависимости.

Если команда сообщает, что node_modules не существует, возможно, в проекте еще не установлено дерево зависимостей или вы находитесь не в том каталоге. Проверьте используемый в проекте менеджер пакетов и lock-файл, прежде чем устанавливать что-либо только для измерения. Lock-файл npm описывает разрешенное дерево зависимостей, тогда как установленные файлы — это именно то, что измеряет du. Документация npm по package-lock

Отслеживание цепочки зависимостей для крупного каталога

Используйте npm ls для проверки логического дерева зависимостей npm. По умолчанию вывод сфокусирован на пакетах верхнего уровня; флаг --all разворачивает список до транзитивных зависимостей. Документация по npm ls

npm ls --all

Для крупного проекта полный список может быть слишком громоздким. Как только вы определите имя потенциального пакета-кандидата из дерева, спросите у npm, почему он установлен:

npm explain package-name

Замените package-name реальным именем, например some-library. Вывод пройдет по цепочке зависимостей вплоть до корневого проекта. Если npm сообщает о наличии нескольких копий или версий, найдите соответствующее место установки в списке и передайте этот путь в команду npm explain, например:

npm explain node_modules/parent-package/node_modules/package-name

В документации npm описано использование npm explain для отслеживания цепочки, приводящей к установке пакета, включая указание конкретной папки при наличии вложенных зависимостей. Документация по npm explain

Анализ пакетов с областью видимости (scope) и вложенных папок

Первое измерение объединяет область видимости, такую как @example, в один каталог. Чтобы проанализировать папки входящих в нее пакетов, выполните:

find node_modules/@example -mindepth 1 -maxdepth 1 -type d -prune -exec du -sh {} + | sort -h

Замените @example областью видимости, которую вы обнаружили на первом этапе. Заключайте путь к scope в кавычки, если используете переменную или путь, содержащий пробелы. Для обычного пакета без scope измеряйте его папку напрямую, например: du -sh "node_modules/some-library". Папка пакета может содержать свои собственные вложенные зависимости; одновременное измерение родительского и вложенного каталогов приведет к двойному учету некоторых файлов, если вы просто сложите их размеры. Используйте эти цифры для поиска кандидатов, а не для подсчета точного объема каждой ветки.

Затем выполните команду npm explain для тяжелого пакета или пути к вложенному пакету, найденному внутри измеренного каталога. Если цепочка ведет через прямую зависимость, то эта зависимость верхнего уровня и является веткой для дальнейшего изучения. Крупный транзитивный пакет также может совместно использоваться несколькими ветками, поэтому его наличие по определенному пути не обязательно означает, что только эта прямая зависимость использует его. npm описывает npm ls как логическое дерево, которое может отличаться от физической структуры каталогов в node_modules; используйте вывод команды explain для понимания связей, а не воспринимайте вложенность папок как полный граф.

Разделение зависимостей разработки и production-зависимостей

Тяжелый инструмент для разработки может быть не нужен в production-установке, в то время как тяжелая runtime-зависимость может требоваться для работы приложения. Изучите цепочку в выводе npm и проверьте, исходит ли она от зависимости разработки (development) или рабочей зависимости (production). Если вы хотите оценить установку пакетов только для production, команда npm ls --omit=dev исключит зависимости для разработки из отображения установленных на диске пакетов; при этом они не удаляются из package.json или lock-файла. Уточните поведение и версию npm перед использованием параметров исключения в процессах автоматизации. Документация по npm install

Относитесь к большому размеру как к подсказке, а не как к доказательству того, что пакет не нужен. Проверьте, что именно импортирует ваше приложение, а также что требуется скриптам сборки и процессу развертывания, прежде чем удалять или заменять зависимость. Если присутствует lock-файл, сверяйтесь с ним при сравнении установок: он фиксирует разрешенное дерево и помогает объяснить, почему другая установка может отличаться от текущего содержимого папки.

Практическая точка завершения анализа

Вы достигли полезного результата, когда можете назвать самый большой по размеру каталог, определить пакет или пакеты внутри него и с помощью npm explain проследить их до корневой зависимости, которая их подтягивает. Это дает вам конкретную ветку для аудита. Сам по себе размер дискового пространства не позволяет решить, безопасно ли удалять ветку, а команды зависимостей npm не вычисляют исключительную долю пакета, если файлы или зависимости используются совместно.

Источники