How to Use pnpm: The Beginner's Guide to Faster, Leaner Node.js Projects
CodexFuse Team · 2026-10-31T03:57:27.257Z · 11 min read min read
A beginner's guide to pnpm: install it the official way, start your first project, add packages, run scripts, and understand the shared store that saves disk space.
What is pnpm, and why are JavaScript developers switching to it?
pnpm is a fast, disk-efficient package manager for Node.js — a drop-in alternative to npm that installs the same packages from the same npm registry, but stores them in one shared place on your disk instead of copying them into every project. If you are learning how to use pnpm, the single idea to grasp first is its content-addressable store: every version of every package is downloaded exactly once, and each of your projects links to it instead of keeping its own duplicate copy.
Think of it like a library. With npm, every student photocopies every book they need and carries the stack home — twenty projects using React means twenty full copies of React on your disk. With pnpm, the library keeps one copy of each book, and every student just gets a bookmark pointing at it. Technically, pnpm keeps all package files in a single global store and then hard-links them (or clones them with copy-on-write where the filesystem supports it) into your projects, so linked files consume no additional disk space, according to the official pnpm motivation documentation.
The store is also clever about versions. If a package has 100 files and a new version changes only one of them, a pnpm update adds just that one new file to the store instead of cloning the whole package again, per the same official documentation. Installation is pipelined too: pnpm resolves, calculates the directory structure, and links packages in three overlapping stages, with each package moving to the next stage as soon as it is ready — faster than the traditional resolve-everything, fetch-everything, write-everything sequence.
There is one more difference you will feel immediately: pnpm builds a strict, non-flat node_modules. Only the dependencies you actually declared appear at the top level, linked as symlinks into a virtual store under node_modules/.pnpm. We will come back to why that strictness is a feature, not a bug. If you have not cloned a project to practice on yet, our GitHub beginner guide walks through that first step.
How do you install pnpm on macOS, Windows, and Linux?
The officially recommended way in 2026 is the standalone install script — or plain npm on Windows. pnpm 12 is the current release line, and it ships as a native executable that does not even need Node.js once installed via the script, according to the official pnpm installation documentation.
- macOS or Linux: run
curl -fsSL https://get.pnpm.io/install.sh | sh -in your terminal. (No curl? Usewget -qO- https://get.pnpm.io/install.sh | sh -instead.) - Windows: the docs currently recommend installing through npm, because Windows Defender can block or slow down the standalone executable. Run
npm install -g pnpm— or use the PowerShell scriptInvoke-WebRequest https://get.pnpm.io/install.ps1 -UseBasicParsing | Invoke-Expressionand then add a Defender exclusion withAdd-MpPreference -ExclusionPath $(pnpm store path)in an administrator PowerShell window. - Already have Node.js? Run
npx get-pnpm(needs Node.js 22.13 or newer) ornpm install -g pnpm@latest(needs Node.js 18 or newer). - Verify and update:
pnpm --versionshould print a version number. Later, update withpnpm self-update, and pin a specific version at install time with thePNPM_VERSIONenvironment variable.
A note on Corepack, since older tutorials mention it: guides like freeCodeCamp's teach corepack enable followed by corepack prepare pnpm@latest --activate, and that route still works. But the current official installation page no longer lists Corepack among the recommended methods, so for a clean 2026 setup, prefer the standalone script or the npm route above.
How do you start your first project with pnpm?
Create a folder, run pnpm init, add packages with pnpm add, and run your scripts with pnpm run — the whole flow takes about a minute, and this pnpm for beginners walkthrough assumes you have just installed it.
mkdir my-first-pnpm-app && cd my-first-pnpm-app
pnpm init
pnpm add express
pnpm add -D typescript
pnpm init creates a package.json without interrogating you — unlike npm init, it does not ask a dozen questions or need a -y flag, as freeCodeCamp's guide points out. pnpm add express installs a production dependency, while pnpm add -D typescript (or --save-dev) installs a development dependency. Both commands update package.json and write a pnpm-lock.yaml lockfile.
Cloned someone else's project instead? Just run pnpm install (or the pnpm i shorthand) in the project folder — it reads package.json and recreates node_modules from the lockfile. Add a script to package.json, for example "dev": "node server.js", and start it with pnpm run dev. Once your app runs, our Supabase beginner guide shows how to attach a real database to a JavaScript project.
Where does pnpm actually keep your packages? The pnpm store, explained
Every package version lives exactly once in a single global store on your machine, and your projects link to it. Run pnpm store path to see the exact folder on your system. The defaults, documented by Flavio Copes in October 2026, are ~/Library/pnpm/store on macOS, ~/.local/share/pnpm/store on Linux, and ~/AppData/Local/pnpm/store on Windows.
Inside a project, the chain looks like this: node_modules/hono is a symlink to node_modules/.pnpm/[email protected]/node_modules/hono, which in turn hard-links to the package files in the global store. Your project's node_modules is therefore mostly tiny symlinks — the real bytes live in one place.
How much disk space does that actually save? Flavio Copes measured it: two projects using the Hono web framework took about 50 MB each with npm — roughly 100 MB total. With pnpm, each project's node_modules shrank to about 1 MB of symlinks while the shared store held the real 50 MB, for a total of about 52 MB — roughly half the disk usage, and the savings grow with every additional project. In a second benchmark with four common packages (Hono, Axios, React, TypeScript), npm took 18 seconds and 180 MB, while pnpm finished in 6 seconds with only about 2 MB inside node_modules. As the official docs put it, you save space in proportion to your number of projects and dependencies.
pnpm vs npm: what's actually different?
Same registry, same package.json format, mostly the same commands — the differences are under the hood: how files are stored, how node_modules is laid out, and how strict the dependency rules are.
| npm | pnpm | |
|---|---|---|
| Package storage | A full copy inside every project's node_modules | One copy per version in a global content-addressable store, hard-linked into projects |
node_modules layout | Flat — everything hoisted to the top level | Strict and non-flat — only your declared dependencies appear at the top, as symlinks |
| Undeclared imports | Often work by accident (phantom dependencies) | Fail fast with a "cannot find module" error |
| Lockfile | package-lock.json | pnpm-lock.yaml |
| Install process | Resolve all, fetch all, write all — sequentially | Resolve, structure, link — pipelined per package |
| Disk usage | Grows with every project | Shared across projects; new versions add only changed files |
If you already know npm's commands, here is the translation cheat sheet — compiled from the community guides by freeCodeCamp and others, and valid for the current pnpm:
| What you want | npm / Yarn | pnpm |
|---|---|---|
| Install all dependencies | npm install | pnpm install (or pnpm i) |
| Add a dependency | npm install lodash | pnpm add lodash |
| Add a devDependency | npm install -D typescript | pnpm add -D typescript |
| Remove a dependency | npm uninstall lodash | pnpm remove lodash |
| Update dependencies | npm update | pnpm update |
| Run a script | npm run build | pnpm run build (or just pnpm build) |
| Install a package globally | npm install -g vercel | pnpm add -g vercel |
| Convert an old lockfile | — | pnpm import |
| Run a script in one workspace package | npm -w admin run test | pnpm -F admin run test |
Now, about that strict node_modules — treat it as a feature. Under npm's flat layout, package A can import package B even when B is not listed in A's dependencies, and it silently works; that is a phantom dependency, a bug waiting for a fresh install to expose it. Under pnpm it fails immediately with a module-not-found error, and the fix is honest: run pnpm add for the missing package so it is declared properly. If some older tooling truly cannot cope with symlinks, the official docs note you can set the nodeLinker setting to hoisted for an npm-like layout — but try the strict default first.
How do pnpm scripts work?
Exactly like npm scripts, with one welcome shortcut: you can skip the word run. Anything in your package.json scripts block is runnable.
{
"scripts": {
"dev": "node server.js",
"build": "tsc",
"test": "node --test"
}
}
pnpm run build works, and so does the shorter pnpm build — pnpm lets you call scripts directly by name, a small ergonomic win the community migration guides highlight. pnpm dev starts your server, pnpm test runs your tests. Scripts always execute from the project root, so relative paths behave the same as they do under npm.
What are pnpm workspaces, and when should you use them?
Workspaces let a single pnpm install manage several related packages inside one repository — reach for them the moment you have a frontend, a backend, and a shared library living in the same repo instead of three separate ones.
Create a pnpm-workspace.yaml file at the repo root listing your package folders as globs:
packages:
- 'apps/*'
- 'libs/*'
From the root, pnpm install now installs dependencies for every workspace package at once and writes a single pnpm-lock.yaml. To run a script everywhere, use the recursive flag — pnpm -r build builds each package in dependency order, a pattern the OroCommerce pnpm migration guide documents. To target one package, filter it: pnpm -F admin run test runs the test script only in the package named admin, per the community command cheat sheets.
Workspaces are pnpm's second act — master single-project usage first, then graduate when a monorepo actually earns its complexity. When your project is ready to leave your laptop, our Docker beginner guide shows how to containerize it, and if you do all of this from a terminal, our Neovim beginner guide is the natural next read.
How do you switch an existing npm project to pnpm?
Install pnpm, delete node_modules and the old lockfile, then run pnpm install — most projects switch in under five minutes, and the migration guides from Flavio Copes and the OroCommerce docs agree on the steps.
- Install pnpm using one of the methods above, then commit to one package manager per project — never mix npm and pnpm in the same repo.
- Remove the old artifacts:
rm -rf node_modules package-lock.json(andyarn.lockif you were on Yarn). - Install with pnpm: run
pnpm install. It resolves from your existingpackage.jsonand writespnpm-lock.yaml. Prefer to keep your exact locked versions? Runpnpm importfirst to convert the old lockfile. - Fix phantom dependencies: if the app now throws "cannot find module" for something that worked under npm, that package was never declared — run
pnpm add <package-name>to declare it properly. - Commit the new lockfile: add
pnpm-lock.yamlto version control so every teammate and CI run installs the identical tree.
Run your test suite after switching. In the overwhelmingly common case, everything passes — the packages are the same ones from the same registry; only the plumbing changed.
Sources
pnpm, "Installation" (official documentation, fetched October 30, 2026) — pnpm 12 as the current release line, standalone install scripts for POSIX and Windows, the Windows Defender recommendation to install via npm, the npx get-pnpm and npm install -g pnpm@latest routes with their Node.js version requirements, pnpm self-update, and the PNPM_VERSION pin. https://pnpm.io/installation
pnpm, "Motivation" (official documentation, fetched October 30, 2026) — the content-addressable store, new versions adding only changed files, hard-link and copy-on-write linking with no additional disk space, the three-stage pipelined install, the strict non-flat node_modules with symlinks and the .pnpm virtual store, and the nodeLinker: hoisted escape hatch. https://pnpm.io/motivation
Flavio Copes, "Managing node_modules efficiently with pnpm and Bun" (updated October 27, 2026, fetched October 30, 2026) — default store paths on macOS, Linux, and Windows, the pnpm store path command, the symlink/hard-link chain from project to store, the measured two-project Hono example (~100 MB with npm vs ~52 MB with pnpm), the four-package benchmark (npm 18 s / 180 MB vs pnpm 6 s / ~2 MB in node_modules), and the npm-to-pnpm migration steps. https://flaviocopes.com/managing-node-modules-efficiently/
freeCodeCamp, "How to Use pnpm – Installation and Common Commands" (fetched October 30, 2026) — the Corepack route (corepack enable, corepack prepare pnpm@latest --activate), non-interactive pnpm init, pnpm add / pnpm add -D / pnpm add -g, pnpm install / pnpm i, and pnpm run for scripts. https://www.freecodecamp.org/news/how-to-use-pnpm
dev.to (robort-gabriel), "Pnpm: Faster, Leaner Node.js Package Manager" (fetched October 30, 2026) — the npm/Yarn-to-pnpm command cheat sheet, pnpm import for lockfile conversion, the pnpm-workspace.yaml monorepo setup, and pnpm -F workspace filtering. https://dev.to/robort-gabriel/pnpm-faster-leaner-nodejs-package-manager-save-disk-2epk
OroCommerce Docs, "PNPM Package Manager" (fetched October 30, 2026) — the strict node_modules phantom-dependency example, the npm-to-pnpm migration sequence, and recursive pnpm -r build in monorepos. https://doc.oroinc.com/frontend/pnpm-package-manager/
Frequently asked questions
Is pnpm compatible with npm?
Yes. pnpm installs the same packages from the same npm registry and reads the same package.json format, so your code does not change. If an older build tool cannot handle symlinked node_modules, the official docs let you set nodeLinker to hoisted for an npm-like layout while keeping pnpm's store and speed.
Why does my code fail with "cannot find module" after switching to pnpm?
That is almost always a phantom dependency: your code imports a package that was never listed in package.json, and npm's flat node_modules let it work by accident. pnpm's strict layout exposes it immediately. Run pnpm add for the missing package to declare it properly — your project is now more correct than it was.
How do I update pnpm itself?
Run pnpm self-update. If your project pins pnpm through the packageManager field in package.json, that command updates the pin instead of your global install, per the official installation docs.
Can I use pnpm in Docker or CI?
Yes. The official installation page documents Docker-specific install commands, and the standalone script needs no Node.js beforehand. Commit pnpm-lock.yaml so CI installs the exact same dependency tree every time.
Does pnpm work on Windows?
Yes — pnpm 12 ships prebuilt binaries for Windows x64 and arm64. The docs currently recommend installing via npm on Windows because Windows Defender can block or slow the standalone executable; if you use the standalone script, add a Defender folder exclusion for your store path.