The Real Cost of npm install
Every dependency you add is:
- Bundle size (slows your app)
- Attack surface (security vulnerabilities)
- Maintenance burden (breaking changes, abandoned packages)
- Transitive dependencies (packages of packages you didn't choose)
Here's how to evaluate whether a dependency is worth adding.
The Five-Question Framework
Before npm install [package]:
1. Can I write this in < 20 lines?
If yes: just write it. No dependency needed.
2. How many weekly downloads does it have?
< 10,000/week: potentially unmaintained, check carefully
> 1M/week: widely used, likely well-maintained
3. When was the last commit?
> 2 years: probably abandoned. Look for alternatives.
4. How many open CVEs does it have?
npm audit will tell you. Zero is the target.
5. How many transitive dependencies does it add?
npm install --dry-run shows the count.
A util adding 50 transitive deps is a red flag.
Things to Write Instead of Install
// Don't install: lodash (for one function)
// Write:
function chunk<T>(arr: T[], size: number): T[][] {
return Array.from({ length: Math.ceil(arr.length / size) },
(_, i) => arr.slice(i * size, i * size + size))
}
// Don't install: uuid (for random IDs)
// Use built-in:
const id = crypto.randomUUID()
// Don't install: date-fns (for basic formatting)
// Use built-in:
new Date().toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' })
// Don't install: is-url (for URL validation)
// Use built-in:
function isUrl(str: string): boolean {
try { new URL(str); return true } catch { return false }
}
// Don't install: left-pad (learned this lesson in 2016)
// Use built-in:
'abc'.padStart(10, '0') // '0000000abc'
Security Audit Workflow
# Before shipping:
npm audit
# Fix automatically:
npm audit fix
# Check what changed:
npm audit fix --dry-run
# Force fix (may break things, verify):
npm audit fix --force
# In CI -- fail if critical vulnerabilities:
npm audit --audit-level=critical
Keeping Dependencies Updated
# See outdated packages
npm outdated
# Interactive update tool
npx npm-check-updates -i
# Update all minor/patch:
npx npm-check-updates -u --target minor
npm install
npm test # Verify nothing broke
# Dependabot (GitHub): auto-PRs for security updates
# .github/dependabot.yml
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
ignore:
- dependency-name: '*'
update-types: ['version-update:semver-major']
Tree Shaking: Only Ship What You Use
// WRONG -- imports entire library
import _ from 'lodash'
const result = _.groupBy(items, 'category')
// RIGHT -- imports only what's needed
import groupBy from 'lodash/groupBy'
const result = groupBy(items, 'category')
// EVEN BETTER -- use native (no import)
const result = Object.groupBy(items, item => item.category)
// (Node 21+, modern browsers)
MCP Server Dependencies
MCP servers have the same dependency risks as any Node.js package -- plus they run inside your AI session.
A compromised transitive dependency in an MCP server can access everything the server can access.
The MCP Security Scanner audits MCP server dependencies as part of its security check.
$29/mo at whoffagents.com
Top comments (0)