npm vs pnpm vs yarn: Comparison and Command Cheatsheet

速查库English更新于 2026-11-06

TL;DR

npm decides dependency versions by checking npm-shrinkwrap.json, then package-lock.json, then yarn.lock. pnpm stores dependencies in a content-addressable store shared across projects, adding only files that differ. yarn installs exact versions from yarn.lock when it satisfies package.json and does not check for newer versions. All three use install as the entry command, but saving dependencies differs: npm uses flags like -D, while yarn uses yarn add --dev. For CI, yarn recommends --frozen-lockfile.

Core Comparison Table

Item or pointValue or descriptionCaveat
npm lockfile precedencenpm-shrinkwrap.json > package-lock.json > yarn.lockInstallation is driven in this order
npm default save locationdependencies-D saves to devDependencies, --save-peer to peerDependencies, -O to optionalDependencies
npm exact version-E or --save-exactDefault uses npm's semver range operator
npm production install--production or NODE_ENV=productionSkips devDependencies; --production=false forces full install
npm alias install<alias>@npm:<name>Applies to your project only, does not rename transitive deps
pnpm storageContent-addressable store, hard links or copy-on-writeCopies by default when the filesystem supports neither
pnpm node_modulesNon-flat by default, symlinks only direct depsSet nodeLinker=hoisted if tooling dislikes symlinks
pnpm install stagesResolution, directory structure calculation, linkingEach package advances as soon as ready, no waiting
yarn with no commandRunning yarn equals yarn installPasses through provided flags
yarn lockfile behaviorInstalls locked versions when yarn.lock satisfies package.jsonDoes not check for newer versions
yarn frozen install--frozen-lockfileDoes not generate a lockfile and fails if an update is needed
yarn single version--flatPrompts once to pick one version for multi-range deps, written to resolutions
yarn audit--auditUnlike npm, yarn audits only when requested

Install and Dependency Management Details

npm: lockfile precedence and save flags

Running npm install with no arguments in a package directory installs the modules listed as dependencies in package.json into the local node_modules. Added packages are saved to dependencies by default; use -D, --save-peer, -O, or --no-save to change the location, and -E to save an exact version. When installing a folder inside the project root, its dependencies are installed and may be hoisted; a folder outside the root gets a symlink instead, and --install-links installs its contents like a registry package.

pnpm: disk usage and install speed

pnpm stores dependencies in a content-addressable store: if 100 projects use one dependency, there are no longer 100 copies on disk; if a new version changes 1 of 100 files, pnpm update adds only 1 new file to the store. Installation runs in three stages—dependency resolution, directory structure calculation, and linking—and each package moves on as soon as it is ready. node_modules is non-flat by default, with only direct dependencies symlinked at the root.

yarn: reproducible installs and common flags

yarn replaces npm's --save and --save-dev with yarn add and yarn add --dev. For reproducible dependencies in CI, pass --frozen-lockfile; --check-files verifies installed files in node_modules were not removed; --force refetches all packages; --ignore-scripts skips scripts defined in package.json and its dependencies; --modules-folder <path> sets an alternate node_modules location.

bash
# npm: install and save as a dev dependency with an exact version
npm install node-tap --save-dev --save-exact

# npm: install two versions of the same package under aliases
npm install jquery2@npm:jquery@2 jquery3@npm:jquery@3

# pnpm: install all dependencies (non-flat node_modules by default)
pnpm install

# pnpm: switch to a flat structure if tooling dislikes symlinks
pnpm install --config.nodeLinker=hoisted

# yarn: reproducible install in CI
yarn install --frozen-lockfile

# yarn: force a single version for multi-range dependencies
yarn install --flat

FAQ

Does npm install read yarn.lock?

Yes, but with the lowest precedence. npm decides installation by checking npm-shrinkwrap.json, then package-lock.json, then yarn.lock.

Why does pnpm save disk space?

Because dependencies live in a content-addressable store, and installs hard-link or copy-on-write files from that single location, so the same version is shared across projects.

When does yarn install update yarn.lock?

When yarn.lock is absent or does not satisfy the dependencies listed in package.json, yarn looks for the newest versions that satisfy the constraints and writes them to yarn.lock.

How do I make yarn fail when the lockfile needs an update?

Use yarn install --frozen-lockfile, which does not generate yarn.lock and fails if an update is needed.

How does pnpm's node_modules differ from npm's?

npm and Yarn Classic hoist packages to the root of the modules directory; pnpm by default symlinks only direct dependencies at the root, and you can set nodeLinker to hoisted for a flat layout.

Sources