everyday mac tools

Find and delete old node_modules folders on a Mac

· 6 min read

Every JavaScript project you have ever installed dependencies for has a node_modules folder, and each one stays on disk long after you stop working on the project. On a developer’s Mac, a few dozen of them can add up to many gigabytes. They are safe to delete for any project with a lockfile, because running the install command again rebuilds them exactly.

The work is in finding them all, seeing which are worth removing, and not deleting one you are in the middle of using.

Why these folders get so big

A node_modules folder holds a full copy of every package a project depends on, plus the packages those depend on, for that project alone. Two projects using the same library each get their own copy. Nothing clears them when a project goes quiet, and they sit inside project folders rather than in any cache location, so general storage views file them under Documents or Developer rather than showing them as something disposable.

They are also made of a very large number of very small files. That is why deleting one in Finder can take a long time, why Time Machine spends effort backing them up, and why Spotlight indexes them unless told otherwise.

Find every node_modules folder

Open Terminal. If your projects live in one place, search just there, which is faster. Replace ~/Projects with your own folder, or use ~ to search your whole home folder:

find ~/Projects -type d -name node_modules -prune

The -prune part matters. Without it, find also walks into each node_modules and lists the nested ones inside it, which gives you a long and misleading list.

Searching all of ~ can take a while and may print “Operation not permitted” for protected folders. That is expected and does no harm.

See how much each one is using

A list of paths is not much help without sizes. This version adds sizes and sorts them so the largest are at the bottom:

find ~/Projects -type d -name node_modules -prune -exec du -sh {} + | sort -h

For a single total:

find ~/Projects -type d -name node_modules -prune -exec du -sk {} + | awk '{s+=$1} END {print s/1024/1024 " GB"}'

Now you can decide. The biggest folders belonging to projects you have not opened in months are the obvious first candidates.

To see how old each project is, look at when its lockfile was last changed. In Finder, sort the project folders by Date Modified, or in Terminal run ls -lt ~/Projects to list projects newest first.

Check before you delete

A node_modules folder regenerates reliably when three things are true:

  1. The project has a lockfile, such as package-lock.json, next to package.json. The lockfile records the exact versions, so reinstalling gets the same result.
  2. The packages are still available from wherever they were installed. Very old projects occasionally depend on a version that has been withdrawn, or on a private registry you no longer have access to.
  3. Nobody edited files inside node_modules by hand. It is bad practice, but it happens, and those edits are lost on deletion. If a project uses a patching step that stores changes in a separate folder, it is fine.

If a project fails one of these checks and still matters to you, leave its folder alone or archive the whole project first.

Also close any editor, test runner or development server using a project before deleting its folder. Deleting underneath a running process leads to confusing errors rather than damage, but it is still a waste of an afternoon.

Delete them

One at a time. Once you have picked a folder from the size list:

rm -rf ~/Projects/old-site/node_modules

Check the path carefully before pressing Return. rm -rf does not use the Trash and does not ask for confirmation. It is faster than Finder for folders with this many files, which is the reason to use it.

All of them under one folder. When you are sure everything under a location can go:

find ~/Projects -type d -name node_modules -prune -exec rm -rf {} +

Run the listing version first and read it. Never run this against ~ without looking, because it will also remove folders belonging to tools you installed that bundle their own dependencies.

Rebuilding later. When you return to a project, run npm ci (or npm install) inside it and the folder comes back.

Keep it from filling up again

  • Exclude project folders from Spotlight. System Settings, Spotlight, then add your projects folder to the list of locations it should not search (the exact label varies by macOS version). Indexing thousands of dependency files is wasted work.
  • Exclude node_modules from Time Machine if your backups are slow or large. System Settings, General, Time Machine, Options lets you exclude folders. You can reinstall dependencies; you cannot reinstall your own source code, so exclude only the dependency folders, never the projects.
  • Clean up when you finish a project, not a year later when the disk is full.

Dependency folders are one part of developer disk use. The shared download caches behind them are a separate pile, covered in package caches on a Mac, and if you build Apple platform apps, Xcode data is usually larger still.

If you would rather see it all in one place

Terminal gives you complete control but only covers what you think to search for. Crumb runs a read-only audit of the whole Mac and lets you reclaim by category, including build artifacts, Xcode data and package caches, with the total shown before you commit to anything. The audit and one full cleanup are free; everything else is $9 once. If you come across a folder and are unsure whether it regenerates, Ask Crumb explains what an item is, whether it comes back and what breaks without it, and nothing is deleted until you approve the plan.

Questions

Will deleting node_modules break a project? Not permanently, if the project has a lockfile and its packages are still available. The project will not run until you reinstall dependencies, which recreates the folder.

Why did deleting it in Finder take so long? Finder moves the folder to the Trash and then has to handle every one of its files when you empty it. rm -rf skips the Trash and is usually much quicker for this kind of folder.

Does deleting node_modules free space for dependencies installed globally? No. Global packages live elsewhere and are not inside any project folder. They are usually far smaller than the combined project folders.