Best Practices

AI Rules for Dependency Management

AI installs packages without checking size, license, maintenance status, or security. Rules for dependency audits, bundle impact, lockfile management, update strategies, and supply chain security.

7 min read·February 5, 2025

npm install without checking size, license, maintenance, or security — 500KB added for one utility

Pre-install evaluation, bundle budgets, lockfile management, update strategies, supply chain security

AI Installs Dependencies Without Thinking

AI generates code that: installs the first package it finds (npm install left-pad without checking alternatives), adds heavy dependencies for simple tasks (importing all of lodash for one function), ignores bundle size impact (adding 500KB to the client bundle for a utility), skips security audits (packages with known vulnerabilities), and never updates (dependencies frozen at the version AI was trained on). Each of these creates: bloated bundles, security vulnerabilities, or maintenance debt.

Modern dependency management is: audited (npm audit / pnpm audit before and after install), size-conscious (bundlephobia.com check before adding), lockfile-committed (deterministic installs across environments), strategically updated (Dependabot or Renovate for automated PRs), and supply-chain-verified (integrity hashes, provenance checks). AI generates none of these.

These rules cover: pre-install evaluation, bundle size impact, lockfile management, semantic versioning update strategies, and supply chain security.

Rule 1: Evaluate Before Installing

The rule: 'Before adding a dependency, check: bundle size (bundlephobia.com — is it tree-shakeable?), maintenance status (last commit, open issues, release frequency), download count (is it widely used and battle-tested?), license compatibility (MIT/Apache OK, GPL may not be), and alternatives (can you write 10 lines instead of adding a package?). A dependency is a commitment — maintenance, security updates, and bundle weight for the life of your project.'

For the 10-line rule: 'If a dependency can be replaced with 10 lines of code, write the code. date-fns: probably worth the dependency (date manipulation is complex). left-pad: three lines of code. is-odd: one line. is-number: typeof x === 'number'. Every dependency is: a supply chain risk (it can be compromised), a maintenance burden (it needs updates), and a bundle cost (it adds bytes). Small utilities are better written inline.'

AI generates: npm install moment (2.5MB, deprecated) for formatting a single date. date-fns with tree-shaking: import { format } from 'date-fns' (adds 2KB for one function). Or Intl.DateTimeFormat (built-in, zero bundle cost). The right dependency is sometimes no dependency.

  • Check bundlephobia.com — size, tree-shakeability, download count
  • Check maintenance: last commit, open issues, release frequency
  • Check license: MIT/Apache OK, GPL requires careful evaluation
  • 10-line rule: if replaceable with 10 lines, write the code instead
  • Consider built-in APIs: Intl, URL, crypto, fs — zero bundle cost
💡 The 10-Line Rule

left-pad: three lines of code. is-odd: one line. is-number: typeof check. Every dependency is a supply chain risk + maintenance burden + bundle cost. If you can write it in 10 lines, write it. Save dependencies for genuinely complex problems.

Rule 2: Bundle Size Impact Analysis

The rule: 'Measure the bundle size impact of every new dependency. Tools: bundlephobia.com (quick check before install), webpack-bundle-analyzer (visual treemap of your bundle), size-limit (CI check that fails if the bundle exceeds a threshold). Set a budget: client-side JavaScript should be under 200KB gzipped for initial load. Every dependency that increases this budget must justify its weight.'

For tree-shaking: 'Prefer packages that support tree-shaking (ES module exports). import { debounce } from 'lodash-es' includes only debounce (1KB). import { debounce } from 'lodash' includes the entire library (70KB). Check package.json for: "module" or "exports" fields (ES module entry points), "sideEffects": false (safe to tree-shake). If a package does not support tree-shaking, look for a modular alternative.'

AI generates: import _ from 'lodash' (70KB) to use _.get() (which optional chaining replaced: obj?.nested?.value). Or import moment from 'moment' (300KB gzipped) to format one date. Each unnecessary kilobyte adds to load time. On a 3G connection, 100KB extra = 1 second extra load time. Bundle budgets enforce discipline.

Rule 3: Lockfile Commitment and Determinism

The rule: 'Always commit the lockfile (pnpm-lock.yaml, package-lock.json, yarn.lock). The lockfile ensures: every developer, CI pipeline, and production deployment installs exactly the same dependency versions. Without the lockfile: pnpm install resolves 'latest compatible version' which may differ between machines (a bug on one machine that does not reproduce on another).'

For lockfile hygiene: 'Review lockfile diffs in PRs — they show exactly which packages changed and to which versions. Suspicious changes: a dependency you did not update changed versions (transitive update), a new package appeared that you did not install (pulled in as a dependency), or integrity hashes changed (potential supply chain attack). The lockfile diff is a security review — not just housekeeping.'

AI generates: .gitignore with pnpm-lock.yaml or package-lock.json listed. The lockfile is not committed. Every install resolves dependencies fresh. Developer A has lodash@4.17.20, developer B has lodash@4.17.21 (with a breaking bug). Production has lodash@4.17.19 (from last week build). Three environments, three different dependency trees, three different behaviors.

⚠️ Three Environments, Three Dependency Trees

Without a committed lockfile: developer A has v4.17.20, developer B has v4.17.21, production has v4.17.19. Same code, different behavior. The lockfile ensures everyone installs exactly the same versions. Commit it. Always.

Rule 4: Semantic Versioning Update Strategies

The rule: 'Use automated dependency update tools (Renovate or Dependabot) with merge strategy: auto-merge patch updates (bug fixes), manual review for minor updates (new features), and careful evaluation for major updates (breaking changes). Pin exact versions in production-critical applications (no ^ or ~ prefix): "react": "19.0.0" not "^19.0.0". This prevents surprise updates from semver-range resolution.'

For security updates: 'Configure Dependabot/Renovate to: create PRs immediately for security vulnerabilities (not batched with regular updates), label security PRs distinctly, and auto-merge critical severity patches if tests pass. Security updates should bypass the normal review cadence — a known vulnerability is actively exploitable.'

AI pins dependencies at whatever version it was trained on. Two years later: 200 outdated packages, 15 known vulnerabilities, and a migration that takes weeks because the gap is too large. Regular updates (weekly patch, monthly minor) keep the gap small and the migration effort minimal.

  • Auto-merge patch updates (bug fixes) if tests pass
  • Manual review for minor updates (new features) — check changelog
  • Careful evaluation for major updates — breaking changes need migration
  • Pin exact versions in production: "react": "19.0.0" not "^19.0.0"
  • Security updates bypass normal cadence — immediate PR, auto-merge if tests pass

Rule 5: Supply Chain Security

The rule: 'Verify package integrity at multiple levels: lockfile integrity hashes (npm/pnpm verify checksums on install), npm provenance (packages signed by CI, verifiable build origin), Socket.dev or Snyk for supply chain analysis (detect typosquatting, suspicious code changes, maintenance handoffs), and internal package mirrors (Artifactory, Verdaccio) for air-gapped or compliance-critical deployments.'

For typosquatting defense: 'Typosquatting: attacker publishes 'loadash' (misspelling of 'lodash') with malicious code. AI is particularly vulnerable — it can generate typos in package names. Defense: use exact package names from documentation, verify the package on npmjs.com before installing, and use Socket.dev to flag suspicious new dependencies in PRs.'

AI generates: npm install [package-name] with no verification. The package could be: typosquatted (similar name, malicious code), compromised (maintainer account hacked, malicious update pushed), or abandoned (no security patches). Supply chain attacks are increasing — event-stream, ua-parser-js, colors.js were all real incidents. Integrity verification is not paranoia, it is due diligence.

ℹ️ AI Types Typos Too

AI can generate 'loadash' instead of 'lodash' — typosquatters publish malicious packages with common misspellings. Verify package names on npmjs.com before installing. Socket.dev flags suspicious new dependencies in PR reviews.

Complete Dependency Management Rules Template

Consolidated rules for dependency management.

  • Evaluate before installing: size, maintenance, license, alternatives, 10-line rule
  • Bundle budget: 200KB gzipped client JS, measured in CI with size-limit
  • Tree-shakeable packages: ES modules, sideEffects: false — lodash-es not lodash
  • Commit lockfile: deterministic installs across all environments
  • Review lockfile diffs: unexpected changes may indicate supply chain issues
  • Automated updates: Renovate/Dependabot — patches auto-merged, minors reviewed
  • Security updates bypass normal cadence — immediate, auto-merged if tests pass
  • Supply chain verification: integrity hashes, provenance, Socket.dev analysis