Package managers. They fetch the open-source libraries your project depends on, resolve their dependency trees and lock exact versions so every machine installs the same thing.
Type a command and watch the package manager fetch a package, resolve its dependency tree and write a lockfile — exactly what happens when you run it for real. Switch managers to see how the syntax differs.
Install the same three apps and npm/yarn copy every dependency into each project's node_modules. pnpm stores one global copy and hard-links it in — so it uses a fraction of the disk. Click to install three projects and compare.
They all read package.json and write a lockfile — only the commands and the internals differ.
Ships with Node.js. The universal baseline — everyone has it. Lockfile: package-lock.json.
npm install react
npm run dev
Brought speed, workspaces and offline caching. Lockfile: yarn.lock.
yarn add react
yarn dev
Content-addressable global store + hard links = tiny, fast, strict installs. Lockfile: pnpm-lock.yaml.
pnpm add react
pnpm dev
package.json lists the versions you want (often as ranges). The lockfile records the exact versions that were actually installed, so every teammate and every CI server gets a byte-for-byte identical tree.
// package.json — what you ask for { "name": "my-app", "dependencies": { "react": "^18.2.0", // ^ = 18.x, latest minor "react-dom": "^18.2.0" }, "scripts": { "dev": "vite", "build": "vite build" } }
# pnpm-lock.yaml — what was actually installed (excerpt) react: 18.2.0 resolved: 'https://registry.npmjs.org/react/-/react-18.2.0.tgz' integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfgszVT...