A dependency folder for one small React app is around 300MB. A Next.js project with a testing stack is closer to 800MB. Neither number matters on its own. What matters is that the folders multiply: every tutorial you followed, every repo you cloned to read one file, every side project you started in a weekend and never opened again still has one sitting on disk.
Developers who guess 5GB usually find 40GB.
Count them first
find ~ -name node_modules -type d -prune 2>/dev/null | wc -l
The -prune flag stops find from descending into a folder once it finds one, which matters because dependency trees nest deeply and the unpruned version is dramatically slower. On a laptop used for web work for three years, counts between 40 and 200 are normal.
Now see which ones are worth deleting
Size them individually and sort, biggest first:
find ~ -name node_modules -type d -prune 2>/dev/null -exec du -sh {} + | sort -hr | head -20
This is the list that usually surprises people. Projects you consider finished still hold 600MB each, and a monorepo can hide four nested copies in packages you forgot existed.
Do not just delete everything
Mass deletion is tempting and mostly harmless, since npm install rebuilds any folder. Two things are worth knowing before you run it:
- You need network access and time to reinstall. On a slow connection, restoring one large project can take longer than the disk space was worth.
- Some projects are pinned to versions that no longer resolve, or use private registries that need credentials. If a project cannot reinstall cleanly today, deleting its dependencies turns a working checkout into a debugging session.
The Analyze tab in macoptimize renders your home folder as a treemap, so every dependency tree shows up as a rectangle sized by its real contents. In our own scan, Projects held 21.90 GB and the biggest blocks inside it were dependency folders attached to repos nobody had opened in months. You click a block, see the path, and decide.
The folders you actually want to remove
Work down the sorted list and apply one rule: if the project folder has not been modified in six months and the git remote still exists, delete its dependencies. You can always clone and install again. The version control history is what matters, not the local copy of lodash.
cd ~/Projects/old-experiment && rm -rf node_modules
For the ones you are unsure about, check whether the repo is pushed before removing anything. If the remote is up to date, the folder is disposable.
The habit that stops the pile growing
Add a cleanup pass to your routine instead of waiting for a disk warning. Two minutes a month keeps the total under a few gigabytes, and the alternative is what most people do: notice at 2GB free, panic, and delete everything including the folders they need.
macoptimize groups every dependency folder it finds by project and age in the Clean tab, and records each removal in the History tab, so the next scan starts from evidence rather than guesswork.
The folders next door that grow just as fast
Dependencies are only half of it. Every tool in the chain keeps its own build output beside them, and those folders are deleted even less often because nothing reminds you they exist.
| Folder | What made it | Typical size |
|---|---|---|
| .next | Next.js production build | 200MB to 2GB |
| dist, build, out | Any bundler | 50MB to 1GB |
| .turbo | Turborepo run cache | 500MB to 10GB |
| .parcel-cache, .vite | Bundler intermediate output | 100MB to 1GB |
| .venv, venv | Python virtual environments | 200MB to 2GB |
| Pods, Carthage/Build | iOS dependency managers | 300MB to 3GB |
| coverage | Test reports nobody reads twice | 10MB to 500MB |
Run the same prune trick once with these names added and you get a much larger number:
find ~/Projects -type d \( -name node_modules -o -name .next -o -name .turbo -o -name dist -o -name .parcel-cache \) -prune 2>/dev/null -exec du -sh {} + | sort -hr | head -30
Clear by age instead of by location
The question that decides all of this is not "how big is this folder" but "have I touched this project since summer". Let find answer it for you:
find ~/Projects -maxdepth 3 -name node_modules -type d -prune -mtime +120 -print
That lists dependency folders inside project folders that have not changed in about four months. Add -exec du -sh {} + to see the totals before you commit to anything, then swap -print for -exec rm -rf {} + once the list looks right.
Never run this while a dev server or a watch task is running. Deleting a folder that a running process has open gives you confusing failures in the terminal and, worse, half deleted trees that look present but fail to resolve. Stop the server, close the editor, then clean.
What a reinstall really costs
Deleting is instant. Restoring is the part worth planning, so here are honest numbers for a 400MB project on a normal connection:
npm cifrom an existing lockfile: roughly 20 to 60 seconds, and it installs exactly what the lockfile pins.npm installwith a cold cache: 40 seconds to 3 minutes, because packages download again.pnpm install: usually the fastest of the three, since packages are hard linked from a global content addressed store instead of copied into every project.- A private registry behind a VPN: unpredictable, and the case where deleting dependencies on a whim hurts most.
Keep a lockfile in version control and never commit node_modules itself, and the whole exercise stays reversible.
Why the count keeps climbing
Every npx command that scaffolds a project, every branch you check out with its own dependency state, and every coding tutorial you follow leaves a folder behind. A worked example: 60 projects at an average of 500MB is 30GB, and it is invisible in Finder because the folders sit deep inside directories you never open. Count them once a quarter and the number stops being a surprise.
FAQ
Will deleting node_modules break anything besides the project?
No. The folder is local build input, not shared state. Nothing outside that project reads it, no other project can use it, and version control ignores it by convention. The only cost is reinstalling before you run the project again.
How much can I realistically reclaim?
On a laptop used for web work for three years, 10GB to 40GB is a normal result, and big monorepos push past that. The count matters more than any single project: 60 folders at 500MB is 30GB even though each one looks harmless.
Does the same problem exist for Python or Ruby projects?
Yes, with different names. Python virtual environments in .venv or venv, Ruby gems in vendor/bundle, and Composer vendor folders all behave the same way. Some are also path dependent, so a virtual environment that was created in a folder you later renamed may already be broken and safe to remove.
Is pnpm better than npm for disk space?
Yes, and by a wide margin on machines with many projects. pnpm keeps one copy of each package version in a global store and hard links it into each project, so ten projects sharing React cost roughly one copy rather than ten. Yarn in Plug and Play mode does something similar by removing node_modules entirely.
Should I delete build folders like .next and dist as well?
Yes, they are pure output and regenerate on the next build or dev server start. Just remember that the next start will be slower and will re-run whatever compile step produced the folder, which for a large Next.js app can be a minute or two.