node_modules is Why Your Mac is Full: Find and Delete All of Them
node_modules folders silently consume tens of gigabytes on your Mac. Find every one, delete them safely, and clean package caches.
I had 47 node_modules folders totaling 38GB on my Mac. Most of them were for projects I hadn’t touched in months. A weekend tutorial from last year? Still has its node_modules. That side project I abandoned after two commits? node_modules. A cloned repo I opened once to read the source? You guessed it — node_modules.
If your Mac keeps telling you the disk is full and you’re a JavaScript developer, there is a very good chance that node_modules is the single biggest reason why. It’s not your photos. It’s not your music. It’s 200,000 tiny files spread across dozens of forgotten project directories.
Let’s fix that.
Why node_modules Gets So Absurdly Big
If you’ve ever looked at a fresh node_modules folder and wondered how a project with three dependencies ended up with 900MB of installed packages, you’re not imagining things. There are real structural reasons why this happens.
Flat Dependency Trees
npm v3 introduced flat dependency trees to solve the deeply nested paths problem on Windows. The trade-off? Every transitive dependency gets hoisted to the top level of node_modules. Install create-react-app and you’ll find yourself with 1,400+ packages in a flat directory. Your project depends on 5 things. Those 5 things depend on 1,395 other things. All of them live in your project folder.
Duplicate Packages Across Projects
Here’s where the math gets painful. If you have 10 React projects on your machine, you likely have 10 complete copies of React, 10 copies of webpack, 10 copies of TypeScript, and 10 copies of every shared dependency between them. There’s no deduplication across projects. Each node_modules is an island.
A typical React project’s node_modules weighs 300-500MB. A Next.js project can hit 600MB-1GB. Multiply that by every project on your machine and you start to see how 20-50GB disappears silently.
Native Binaries and Platform-Specific Code
Some packages include prebuilt native binaries — esbuild, swc, sharp, better-sqlite3, Playwright’s browser binaries. These are often 50-200MB each. They compile or download platform-specific builds during npm install, and they’re not small.
Build Output Hiding in Plain Sight
On top of node_modules itself, most JavaScript projects also generate build output directories: dist, build, .next, .nuxt, out. A Next.js build cache (.next) alone can be 200-500MB. These add up across projects too, and they’re just as safe to delete as node_modules — they regenerate on the next build.
Finding All node_modules on Your Mac
Before you delete anything, let’s see the damage. This command finds every node_modules directory under your home folder and shows its size:
find ~ -name "node_modules" -type d -maxdepth 5 -exec du -sh {} \; 2>/dev/null
You’ll see output like this:
1.2G /Users/you/projects/webapp/node_modules
487M /Users/you/projects/api-server/node_modules
923M /Users/you/code/nextjs-blog/node_modules
341M /Users/you/tutorials/react-course/node_modules
756M /Users/you/clients/dashboard/node_modules
...
Want just the total? Pipe it through awk:
find ~ -name "node_modules" -type d -maxdepth 5 -exec du -sm {} \; 2>/dev/null | awk '{total += $1} END {printf "Total: %.1f GB\n", total/1024}'
Fair warning: this command can take a minute or two to run. du has to stat every file inside every node_modules, and there are a lot of files.
If you want a quick count of how many node_modules folders you have without waiting for sizes:
find ~ -name "node_modules" -type d -maxdepth 5 2>/dev/null | wc -l
Don’t be surprised if it’s more than you expected. I never would have guessed 47.
The Nuclear Option: Delete Them All
Once you’ve seen the list, you’ll probably realize that most of these projects don’t need their dependencies installed right now. You can always run npm install (or yarn, or pnpm install) again later when you actually work on a project. The package.json and lockfile are what matter — node_modules is just a cache.
To delete every node_modules folder under your home directory:
find ~ -name "node_modules" -type d -maxdepth 5 -exec rm -rf {} + 2>/dev/null
A few things to know before you run this:
- It’s safe. node_modules is fully regenerable from your lockfile. Nothing unique lives in there.
- Running projects will break. If you have a dev server running, it will crash. Stop your dev servers first.
- You’ll need to reinstall. The next time you
cdinto a project and run it, you’ll need tonpm installfirst. This is normal. - It won’t touch your source code. Only the
node_modulesdirectories are deleted. Yourpackage.json, lockfiles, and source files are untouched.
If you want to be more selective — say, only delete node_modules for projects you haven’t modified in over 30 days — that’s harder to do from the command line. You’d need to cross-reference each node_modules with the modification dates of the source files in the parent project directory. (This is actually something MegaCleaner does automatically — more on that below.)
Package Manager Caches: The Other Storage Hog
Deleting node_modules folders is only half the story. Your package manager also keeps a global cache of downloaded packages. This cache speeds up future installs so npm doesn’t have to re-download packages from the registry, but it grows over time and can get large — especially if you work across many projects with different dependency versions.
Here’s where each package manager stores its cache on macOS and how to clean it.
npm
Cache location: ~/.npm
npm’s cache stores tarballs and metadata for every package you’ve ever installed. It grows indefinitely.
# Check size
du -sh ~/.npm
# Clean it
npm cache clean --force
The --force flag is required because npm wants you to really mean it. After cleaning, future installs will be slightly slower for the first run as packages are re-downloaded.
Yarn (v1/Classic)
Cache location: ~/Library/Caches/Yarn
You can verify the exact path on your system:
yarn cache dir
To clean it:
# Check size
du -sh ~/Library/Caches/Yarn
# Clean it
yarn cache clean
pnpm
Cache location: ~/Library/pnpm
pnpm uses a content-addressable store, which is actually more efficient than npm or yarn — it deduplicates packages across projects using hard links. That said, the store still grows over time as you install different package versions.
# Check size
du -sh ~/Library/pnpm
# Remove unreferenced packages
pnpm store prune
pnpm store prune is gentler than a full delete — it removes packages that aren’t referenced by any project on your machine, but keeps the ones that are still in use.
Bun
Cache location: ~/.bun/install/cache
Bun’s cache stores downloaded packages in its own format:
# Check size
du -sh ~/.bun/install/cache
There’s no built-in bun cache clean command as of this writing. To clear it, you can delete the directory manually:
rm -rf ~/.bun/install/cache
Deno
Cache location: ~/.deno
Deno stores downloaded dependencies and compilation caches here:
# Check size
du -sh ~/.deno
Turborepo
Cache location: ~/.turbo
If you use Turborepo for monorepo build orchestration, it maintains a global build cache:
# Check size
du -sh ~/.turbo
The One-Liner to Check All of Them
Want to see how much space all your package manager caches are consuming? Run this:
echo "=== Package Manager Caches ===" && \
du -sh ~/.npm 2>/dev/null; \
du -sh ~/Library/Caches/Yarn 2>/dev/null; \
du -sh ~/Library/pnpm 2>/dev/null; \
du -sh ~/.bun/install/cache 2>/dev/null; \
du -sh ~/.deno 2>/dev/null; \
du -sh ~/.turbo 2>/dev/null
In my experience, the combined size of these caches ranges from 2-10GB depending on how many different projects and package versions you’ve worked with.
Prevention Tips: Keeping node_modules Under Control
Deleting everything feels great, but it’ll grow back. Here are some strategies to keep node_modules from swallowing your disk again.
Use pnpm Instead of npm
pnpm’s content-addressable store means that if 10 projects use the same version of React, only one copy exists on disk. Each project’s node_modules contains hard links to the central store. In practice, this reduces total disk usage by 50-70% compared to npm.
Switching is straightforward — pnpm uses the same package.json format and can import existing lockfiles:
npm install -g pnpm
pnpm import # converts package-lock.json to pnpm-lock.yaml
pnpm install # creates a linked node_modules
Configure .npmrc for Smaller Installs
Add these to your ~/.npmrc to reduce what gets installed:
# Don't install optional dependencies (often native binaries you don't need)
optional=false
# Disable package-lock generation for throwaway projects
# (only use this for experiments, not real projects)
# package-lock=false
Clean Up Regularly
Set a reminder to clean node_modules every month or two. Or, if you want to remember which projects are stale, use ls -la on your project directories and sort by modification date:
# List projects by last modification date
ls -lt ~/projects/*/package.json 2>/dev/null | head -20
Don’t Forget Build Artifacts
JavaScript build tools generate output directories that are just as safe to delete as node_modules. Common ones include:
dist/— Vite, Rollup, webpack, esbuildbuild/— Create React App, various tools.next/— Next.js build cache and output.nuxt/— Nuxt.js build outputout/— Next.js static export, other tools
These regenerate on the next npm run build. If a project is sitting idle, there’s no reason to keep them around.
The Automated Way: Let MegaCleaner Handle It
The command-line approach works, but it has limitations. find is slow on large directory trees, it can’t tell you which projects are stale versus actively in use, and you have to remember to run it. Plus, manually tracking six different cache directories across four package managers gets old.
MegaCleaner is a native macOS app I built specifically for this problem. Its Node.js scanner handles all of the above automatically:
What it finds:
- Every
node_modulesfolder across all your project directories and external drives - Package manager caches: npm (
~/.npm), Yarn (~/Library/Caches/Yarn), pnpm (~/Library/pnpm), Bun (~/.bun/install/cache), Deno (~/.deno) - Turborepo global build cache (
~/.turbo) - JS/Web build artifacts (
dist,build,.next,.nuxt,out) in any project that has apackage.json
What makes it smarter than find:
- Staleness detection. MegaCleaner checks the modification dates of actual source files in each project (
.js,.ts,.tsx,.vue,.svelte,.astro,.json,.css,.scss, and more) — not just the node_modules folder itself. If you haven’t edited source code in a project for months, it marks that project’s node_modules as stale and pre-selects it for cleanup. - Project name detection. It reads each project’s
package.jsonto show you human-readable project names instead of raw directory paths. - Package manager awareness. It detects which package manager each project uses by checking for lockfiles (
bun.lockb,pnpm-lock.yaml,yarn.lock,package-lock.json) and shows you the correct reinstall command (bun install,pnpm install,yarn, ornpm install). - No nested duplicates. It skips
node_modulesinside othernode_modulesfolders to avoid double-counting, and follows canonical paths to prevent counting symlinked directories twice. - Symlink safety. It skips symbolic links entirely to avoid infinite loops and accidental deletion of linked directories.
Node.js is just one of MegaCleaner’s 29 scanners. It also covers Xcode DerivedData, Docker images, Python virtual environments, Rust target directories, Go module caches, Homebrew leftovers, and more. If you’re a polyglot developer, the savings add up fast.
MegaCleaner is a one-time purchase: $49, no subscription. It’s a native macOS app — no Electron, no web views.
Quick Reference: Commands Checklist
Here’s everything from this article in one place. Bookmark this section.
Find all node_modules and their sizes:
find ~ -name "node_modules" -type d -maxdepth 5 -exec du -sh {} \; 2>/dev/null
Delete all node_modules:
find ~ -name "node_modules" -type d -maxdepth 5 -exec rm -rf {} + 2>/dev/null
Clean npm cache:
npm cache clean --force
Clean Yarn cache:
yarn cache clean
Prune pnpm store:
pnpm store prune
Delete Bun cache:
rm -rf ~/.bun/install/cache
Check all cache sizes at once:
du -sh ~/.npm ~/Library/Caches/Yarn ~/Library/pnpm ~/.bun/install/cache ~/.deno ~/.turbo 2>/dev/null
JavaScript’s dependency model means node_modules will always come back. The key is not to let it sit around consuming space in projects you’re not actively working on. Whether you set up a monthly terminal ritual or let MegaCleaner handle it automatically, your Mac’s storage will thank you.