What it is
A fast, disk-space-efficient package manager for Node.js, prioritizing speed and efficient dependency management.
Installation
Linux/macOS:
curl -fsSL https://get.pnpm.io/install.sh | sh -
Windows (using npm):
npm install -g pnpm
Windows (using PowerShell):
iwr https://get.pnpm.io/install.ps1 -UseBasicParsing | Select-String -Pattern 'Invoke-Expression' | ForEach-Object { $_.Line } | Invoke-Expression
Core Concepts
- Symlinked
node_modules: pnpm uses a global, content-addressable store (~/.pnpm-store) for all packages. In your project,node_modulesis populated with symlinks to these globally stored packages. This avoids duplicated packages across projects and saves disk space. - Non-flat
node_modules: Unlike npm or yarn, pnpm creates anode_modulesstructure that mirrors yourpackage.jsondependencies, rather than flattening everything. This strictly enforces dependency rules, preventing accidental usage of undeclared dependencies. - Workspaces: pnpm has robust support for monorepos, allowing you to manage multiple related packages within a single repository.
Commands / Usage
Project Initialization & Setup
-
Initialize a new project:
pnpm initCreates a
package.jsonfile for a new Node.js project. -
Initialize a new project with a template:
pnpm init typescriptInitializes a project with a specific template (e.g., TypeScript).
Package Management
-
Add a dependency:
pnpm add reactInstalls the
reactpackage and adds it todependenciesinpackage.json. -
Add a dev dependency:
pnpm add -D jestInstalls the
jestpackage and adds it todevDependenciesinpackage.json. -
Add a peer dependency:
pnpm add -P eslintInstalls the
eslintpackage and adds it topeerDependenciesinpackage.json. -
Add a global dependency:
pnpm add -g http-serverInstalls the
http-serverpackage globally, making it available as a command-line tool. -
Install all dependencies from
package.json:pnpm installInstalls all dependencies listed in
package.jsonandpnpm-lock.yaml. -
Install specific dependencies:
pnpm install lodash expressInstalls
lodashandexpressand adds them todependencies. -
Install dependencies for production:
pnpm install --prodInstalls only production dependencies (skips
devDependencies). -
Install dependencies with a specific lockfile:
pnpm install --frozen-lockfileInstalls dependencies based strictly on the
pnpm-lock.yaml, failing ifpackage.jsondiffers. -
Remove a dependency:
pnpm remove reactUninstalls the
reactpackage and removes it frompackage.json. -
Remove a dev dependency:
pnpm remove -D jestUninstalls the
jestpackage and removes it fromdevDependencies. -
Update dependencies:
pnpm updateUpdates all dependencies to their latest versions according to
package.jsonandpnpm-lock.yaml. -
Update a specific dependency:
pnpm update reactUpdates the
reactpackage to its latest allowed version. -
Update to a specific version:
pnpm update react@^18.0.0Updates
reactto the latest version compatible with^18.0.0. -
List installed packages:
pnpm listLists all installed packages and their versions.
-
List dependencies of a specific package:
pnpm list --depth=0Lists only the top-level dependencies.
-
Run a script defined in
package.json:pnpm run buildExecutes the
buildscript from yourpackage.json. -
Run a script with arguments:
pnpm run test -- --watchExecutes the
testscript and passes--watchas an argument to it. -
Execute a package binary:
pnpm exec eslint .Runs the
eslintcommand from the installed packages.
Workspaces (Monorepos)
-
Install dependencies for all workspace packages:
pnpm installRuns
pnpm installat the root of a workspace. -
Add a dependency to a specific workspace package:
pnpm add lodash -C packages/backendAdds
lodashto thepackages/backendworkspace package. -
Run a script in all workspace packages:
pnpm run build --filter ./packages/*Runs the
buildscript in all packages underpackages/. -
Run a script in a specific workspace package:
pnpm run test --filter @my-org/frontendRuns the
testscript in the@my-org/frontendpackage. -
Run a script in packages that depend on another package:
pnpm run build --filter @my-org/shared-ui...Runs
buildin packages that are direct or indirect dependents of@my-org/shared-ui. -
Run a script in packages that a package depends on:
pnpm run lint --filter ...@my-org/shared-uiRuns
lintin packages that@my-org/shared-uidirectly or indirectly depends on.
Configuration & Management
-
View pnpm configuration:
pnpm config listDisplays the current pnpm configuration values.
-
Set pnpm configuration:
pnpm config set store-dir ~/.my-pnpm-storeSets the global store directory.
-
Remove the global store:
pnpm store pruneRemoves unused packages from the global store.
-
Get the path to the pnpm store:
pnpm store pathPrints the absolute path to the global pnpm store.
Common Patterns
-
Clean install (remove
node_modulesand reinstall):rm -rf node_modules && pnpm installEnsures a fresh installation by removing the existing
node_modulesdirectory. -
Install with specific Node.js version (using
npxorvolta):# Using npx (requires Node.js to be installed) npx pnpm install # Using volta (if installed) volta run pnpm installEnsures that the installation happens with a specific Node.js version managed by
npxorvolta. -
Running a script and ignoring potential errors (for CI):
pnpm install --ignore-scriptsInstalls dependencies without executing any lifecycle scripts.
-
Build a project for production:
pnpm install --prod && pnpm run buildInstalls only production dependencies and then builds the project.
-
Updating dependencies and committing changes:
pnpm update && git add pnpm-lock.yaml package.json && git commit -m "chore: update dependencies"A common workflow for updating all dependencies and committing the lockfile.
-
Checking for outdated packages:
pnpm outdatedLists packages that have newer versions available than what’s currently installed.
Gotchas
- Global package conflicts: While
pnpm add -gis convenient, managing global packages can lead to conflicts if different projects require different versions of the same global tool. Consider usingnpxorpnpm execfor project-specific tool execution. - Symlink issues in some environments: In rare cases, particularly with older Windows versions or specific IDE configurations, symlinks might behave unexpectedly. pnpm’s strict dependency structure can sometimes expose these underlying OS behaviors.
pnpm-lock.yamlvspackage-lock.json/yarn.lock: pnpm uses its own lockfile format. Do not mix or attempt to convert lockfiles from other package managers; usepnpm installto generatepnpm-lock.yaml.- Workspace filtering complexity: The
--filtersyntax can be powerful but also complex. Understanding the nuances of package names, paths, and the...operator is key for effective monorepo management. --frozen-lockfilebehavior: This flag is crucial for CI/CD pipelines to ensure reproducible builds. Ifpackage.jsonhas changed since the lockfile was last updated,pnpm install --frozen-lockfilewill error out, which is the desired behavior to catch inconsistencies.