npm / pnpm — Cheat Sheet

Tag: npm, pnpm, node, package-manager, javascript

Livello: intermedio

TL;DR: Quick reference comparing npm and pnpm, highlighting pnpm's space-saving symlink approach, strict dependency resolution, and performance benefits over traditional npm.

Concetti chiave

npm: Default Node.js package manager; uses a flattened node_modules structure which can lead to phantom dependencies.

pnpm: Performant npm; uses a global content-addressable store to save disk space and boost installation speed.

Symlinks & Hard links: pnpm creates hard links from the global store to the project, and uses symlinks to build nested node_modules.

Strictness: pnpm prevents phantom dependencies by ensuring packages can only access modules explicitly declared in their package.json.

Disk Space Efficiency: pnpm shares identical packages and versions across multiple projects on the same machine, drastically reducing disk usage.

Workspaces: Both support monorepos, but pnpm is generally faster and offers more robust workspace filtering out of the box.

Lockfiles: npm uses package-lock.json; pnpm uses pnpm-lock.yaml.

Domande tipiche e risposte pronte

Q: Why should a project migrate from npm to pnpm?R: I would migrate to significantly reduce disk space usage, improve installation times, and enforce a strict node_modules structure that eliminates phantom dependency bugs.

Q: What is a phantom dependency and how does pnpm solve it?R: A phantom dependency is an undeclared package accessible because npm hoists it. pnpm uses a nested symlinked structure that only exposes explicitly declared dependencies.

Q: How do we ensure reproducible builds in CI with pnpm?R: We use pnpm install --frozen-lockfile to ensure deterministic builds based entirely on the existing pnpm-lock.yaml, similar to how npm ci works.

Insidie e errori comuni

Missing dependencies: Projects migrating from npm to pnpm often fail if they relied on phantom dependencies. The fix is to explicitly install the missing packages.

Symlink issues: Legacy tools or specific bundlers might struggle with symlinks. Configuration tweaks, like enabling resolve.symlinks in Webpack, might be required.

Global installs: Using pnpm add -g behaves differently than npm and requires setting up the global bin directory in the system PATH.

Snippet e comandi

# npm commands
npm install             # Install dependencies
npm ci                  # Clean install for CI (requires lockfile)
npm run <script>        # Run a script from package.json

# pnpm equivalents
pnpm install            # Install dependencies
pnpm install --frozen-lockfile # Clean install for CI
pnpm <script>           # Run a script (no 'run' needed)

# Adding packages
pnpm add <pkg>          # npm install <pkg>
pnpm add -D <pkg>       # npm install -D <pkg>

# Workspaces (Monorepo)
pnpm --filter <package-name> run build
Jarvis Interviews
Jarvis