Scans for JavaScript dependency directories and build artifacts.
Usage: ./audit_js_storage.sh [target_directory]
TARGET_DIR="${1:-$HOME}"
MAX_DEPTH=6
echo "=== JavaScript Storage Audit ==="
echo "Scanning: ${TARGET_DIR}"
echo "Max Depth: ${MAX_DEPTH}"
echo "--------------------------------"
Audit node_modules
echo "[1] Scanning node_modules directories..."
find "${TARGET_DIR}" -maxdepth "${MAX_DEPTH}" -type d -name "node_modules" -exec du -sh {} ; 2>/dev/null | sort -rh
Audit common build artifacts
echo "[2] Scanning build artifacts (.next, dist, build, out)..."
find "${TARGET_DIR}" -maxdepth "${MAX_DEPTH}" -type d ( -name ".next" -o -name "dist" -o -name "build" -o -name "out" ) -exec du -sh {} ; 2>/dev/null | sort -rh
echo "--------------------------------"
echo "Audit complete."
#### 2. Safe Purge Mechanism
Direct deletion commands pose risks if executed without verification. The following script introduces a dry-run mode and ensures only `node_modules` directories are targeted, preserving source code and lockfiles.
**File: `safe_purge_deps.sh`**
```bash
#!/usr/bin/env bash
# Safely removes node_modules directories with dry-run support.
# Usage: ./safe_purge_deps.sh [--dry-run]
DRY_RUN_FLAG="${1}"
ACTION_CMD="rm -rf"
if [[ "${DRY_RUN_FLAG}" == "--dry-run" ]]; then
echo "DRY RUN MODE: No files will be deleted."
ACTION_CMD="echo [WOULD REMOVE]"
fi
echo "Initiating purge of node_modules directories..."
# Execute find with exec to handle paths with spaces safely
find "${HOME}" -maxdepth 6 -type d -name "node_modules" -exec ${ACTION_CMD} {} + 2>/dev/null
if [[ "${DRY_RUN_FLAG}" != "--dry-run" ]]; then
echo "Purge complete. Run 'pnpm install' or 'npm install' to regenerate."
fi
3. Unified Cache Management
Global caches for npm, Yarn, pnpm, Bun, and Deno accumulate redundant data. A unified function simplifies maintenance across different package managers.
File: manage_global_caches.sh
#!/usr/bin/env bash
# Prunes caches for all detected JavaScript package managers.
prune_caches() {
echo "=== Global Cache Pruning ==="
# npm
if command -v npm &> /dev/null; then
echo "Pruning npm cache..."
npm cache clean --force 2>/dev/null
fi
# pnpm
if command -v pnpm &> /dev/null; then
echo "Pruning pnpm store..."
pnpm store prune 2>/dev/null
fi
# Yarn Classic
if command -v yarn &> /dev/null; then
echo "Pruning Yarn cache..."
yarn cache clean 2>/dev/null
fi
# Bun
if [[ -d "${HOME}/.bun/install/cache" ]]; then
echo "Clearing Bun cache..."
rm -rf "${HOME}/.bun/install/cache"
fi
# Deno
if [[ -d "${HOME}/.deno" ]]; then
echo "Clearing Deno cache..."
rm -rf "${HOME}/.deno"
fi
# Turborepo
if [[ -d "${HOME}/.turbo" ]]; then
echo "Clearing Turborepo cache..."
rm -rf "${HOME}/.turbo"
fi
echo "Cache pruning complete."
}
prune_caches
4. Migration and Optimization
Migrating to pnpm is the most effective long-term strategy. Use the import command to convert existing lockfiles.
Migration Workflow:
# Install pnpm globally
npm install -g pnpm
# Navigate to project root
cd /path/to/project
# Convert package-lock.json to pnpm-lock.yaml
pnpm import
# Install dependencies using content-addressable store
pnpm install
Configuration Optimization:
Optimize ~/.npmrc to reduce footprint for npm-based projects.
# ~/.npmrc
# Skip optional dependencies to save space on native binaries not required by the project
optional=false
# Limit cache size (npm v7+)
cache-max=5000
Pitfall Guide
-
Process Contention During Deletion
- Explanation: Deleting
node_modules while a development server (e.g., Vite, Next.js, Webpack) is running causes the process to crash or enter an undefined state as file handles are invalidated.
- Fix: Always terminate all active dev servers and background build processes before executing purge scripts.
-
The Global Cache Blind Spot
- Explanation: Removing
node_modules directories only addresses local project artifacts. Global caches in ~/.npm, ~/Library/pnpm, or ~/Library/Caches/Yarn can hold 2β10GB of tarballs and metadata.
- Fix: Always pair local cleanup with global cache pruning using the unified management script.
-
Misconception of Irreplaceable Data
- Explanation: Developers sometimes hesitate to delete
node_modules fearing loss of code. This directory is strictly a derived cache generated from package.json and lockfiles.
- Fix: Verify that
package.json and lockfiles are committed to version control. node_modules can be safely regenerated at any time.
-
Scope Creep in Deletion Commands
- Explanation: Using
find without depth limits or path verification can inadvertently target system directories or external drives, leading to performance degradation or accidental data loss.
- Fix: Always use
maxdepth constraints and perform a dry-run audit before executing deletion commands.
-
Build Artifact Accumulation
- Explanation: Framework output directories like
.next, .nuxt, dist, and build consume space comparable to node_modules and are often forgotten during cleanup.
- Fix: Include build artifacts in audit scripts and purge routines. These directories are also fully regenerable.
-
Hard Link Filesystem Incompatibility
- Explanation: pnpm relies on hard links for its global store. Network drives, FAT/exFAT volumes, or certain containerized environments may not support hard links, causing silent duplication or installation failures.
- Fix: Ensure the global store resides on a local filesystem with hard link support (e.g., APFS, ext4). Avoid placing the store on network mounts.
-
Lockfile Synchronization Errors
- Explanation: After mass deletion, running the wrong package manager (e.g.,
npm install on a pnpm-lock.yaml) breaks deduplication and inflates disk usage.
- Fix: Always use the package manager that corresponds to the existing lockfile. If migrating, use
pnpm import to convert lockfiles explicitly.
Production Bundle
Action Checklist
Decision Matrix
| Scenario | Recommended Approach | Why | Cost Impact |
|---|
| Legacy Monorepo | Migrate to pnpm + pnpm import | Reduces duplication across packages; hardlinks save significant space. | High initial migration effort; long-term storage savings. |
| Throwaway Experiments | .npmrc with optional=false + frequent purge | Minimizes footprint of unnecessary native binaries; quick cleanup. | Low effort; moderate storage savings. |
| CI/CD Environments | Ephemeral runners + cache pruning | Prevents disk exhaustion in constrained environments; ensures clean state. | Reduces build failures due to disk space; improves reliability. |
| Network Drive Projects | Avoid pnpm; use npm/yarn with strict cleanup | Hard links fail on network drives; standard copies are safer. | Higher storage usage; requires disciplined cleanup routines. |
Configuration Template
Shell Aliases for Rapid Management
Add to ~/.zshrc or ~/.bashrc for quick access.
# JavaScript Storage Management Aliases
# Audit storage usage
alias js-audit='find "${HOME}" -maxdepth 5 -type d -name "node_modules" -exec du -sh {} \; 2>/dev/null | sort -rh'
# Quick purge with confirmation
alias js-purge='read -p "Purge all node_modules? [y/N] " -n 1 -r; echo; if [[ $REPLY =~ ^[Yy]$ ]]; then find "${HOME}" -maxdepth 5 -type d -name "node_modules" -exec rm -rf {} + 2>/dev/null; echo "Purge complete."; fi'
# Prune all caches
alias js-cache-clean='npm cache clean --force 2>/dev/null; pnpm store prune 2>/dev/null; yarn cache clean 2>/dev/null; echo "Caches pruned."'
# Check total JS footprint
alias js-total-size='du -sh ~/.npm ~/.pnpm-store ~/Library/Caches/Yarn 2>/dev/null | awk "{sum += \$1} END {print \"Total Cache: \" sum/1024 \" GB\"}"'
Optimized .npmrc for Minimal Footprint
# ~/.npmrc
# Disable optional dependencies to reduce native binary bloat
optional=false
# Limit npm cache size to 5GB
cache-max=5000
# Prefer exact versions to reduce resolution overhead
save-exact=true
Quick Start Guide
- Install pnpm: Run
npm install -g pnpm to enable content-addressable storage.
- Convert Projects: Navigate to existing projects and run
pnpm import followed by pnpm install.
- Run Cleanup: Execute
manage_global_caches.sh to reclaim space from legacy caches.
- Set Up Aliases: Add the provided shell aliases to your profile for ongoing maintenance.
- Schedule Maintenance: Add a cron job or calendar reminder to run
js-audit and js-cache-clean monthly.