Switching from npm to pnpm
Let’s talk about package managers and whether it’s worth using pnpm instead of npm.
It feels like today, if you have even a few GitHub repositories with projects that use various packages, you’ll keep getting all kinds of security alerts constantly. Most of the time it’s about bumping versions to ones where a number of vulnerabilities have been fixed. Sometimes it can be resolved simply by using Dependabot’s automatic process, but often it may require doing something else (since it can’t always fix all update issues). And sometimes certain vulnerabilities can be quite hard to fix, so you may consider using a different package (or dropping the old one entirely).
Sidenote: Around the time of writing this, GitHub announced changes to Dependabot: it now waits three days before creating non-security version update pull requests. It’s less relevant to this post, but I thought it was worth mentioning, as it seems like a good change.
On top of that, if you follow even some of the news in the development world, you’re probably well aware of all kinds of leaks, hacks, and exploits that are becoming increasingly serious. Quite often, they originate from vulnerabilities in installed packages across different projects. And, given that many projects are filled with packages handling all kinds of tasks (from simple icon libraries to authentication and access token handling), this can quickly get out of hand.
One of the possible solutions I keep hearing about is to switch from the default Node.js package manager (npm) to the more performant alternative, pnpm. It is considered safer and can be used in almost the same way. Let’s talk about some differences between the two and potential pros and cons.
I should add the usual disclaimer here: I’m not an expert and simply did a bit of digging to check whether I personally want to switch from one package manager to another. And then I decided to share what I’ve come up with so far. So this isn’t an ultimate “pnpm is beter than npm” (or vice versa) post, more like “food for thought” in case you’re also interested in the subject.
General info on npm / pnpm
Below are a few basic details about npm and pnpm.
npm
- The default Node.js package manager.
- Manages a project’s dependencies and scripts.
- Common commands are: npm install (installs dependencies from package.json), npm install [package name] (adds a new dependency), npm run [script name] (runs scripts defined in package.json), npm uninstall [package name] (removes a dependency).
- Comes with Node.js.
- Uses package-lock.json as its lockfile.
- Installs packages into node_modules.
Sidenote: There is also a runner that comes with npm — npx. Its main job is to run a package without installing it globally or adding it to a project. It’s typically used for tools like Vite (for example: npx create-vite@latest project-name), or to try a CLI without installing it. It downloads the package temporarily, runs the command and leaves without modifying package.json. The main difference with npm is that npx runs once without installation.
pnpm
- An alternative package manager.
- Also manages dependencies and scripts (but in a different way).
- Common commands are: pnpm install (identical to npm install), pnpm add [package name] (adds a new dependency), pnpm run [script name] (runs scripts), pnpm remove [package name] (removes a dependency).
- Uses less disk space and allows faster installs.
- Only allows importing what’s declared in package.json.
- Uses pnpm-lock.yaml instead of package-lock.json.
- Stricter than npm in terms of security (for example, in delaying new versions).
Sidenote: pnpm’s equivalent of npx is “pnpm dlx” (for example, pnpm dlx create-vite@latest project-name). Many tools have a shortcut: pnpm create. There is also pnpm exec that runs a binary from node_modules (like npx but for already-installed packages).
Pros and cons of pnpm
Any tool comes with pros and cons, and the same applies to choosing a package manager. Here’s a short list summarizing the advantages and possible downsides of using pnpm over npm (or vice versa):
- npm copies every package into a project’s node_modules folder (which leads to duplication), while pnpm stores each package version once.
- pnpm saves disk space and increases installation speed.
- npm uses a flat file structure and can accidentally import a package that hasn’t been declared, while pnpm only uses what’s defined in package.json (that also leads to fewer vulnerabilities to exploit).
- pnpm delays new versions to avoid pulling in potentially compromised packages.
- npm also has some of the mentioned features but they are not enabled by default.
- pnpm requires a separate installation, while npm is included in Node.js.
- pnpm can potentially run into issues with older tools/plugins (due to its stricter approach) and may require additional tweaks.
- npm is widely known, while pnpm may require a bit of time to get used to (especially if you’re working in a team).
Switching to pnpm
A typical setup for pnpm would be:
// Installation command (once)
npm install -g pnpm
// Usage
pnpm install
pnpm add [package name]
pnpm run [script name]
pnpm remove [package name]Then in your project’s folder you’ll have pnpm-lock.yaml instead of package-lock.json.
There are other installation options (like using a standalone script instead of a global command). You can check them in the pnpm docs.
If you already have a project where you used npm but now want to switch to pnpm, you can delete node_modules and package-lock.json, then run the pnpm install command. Normally, that’s enough, but obviously there’s a possibility of some specific issues that may need to be resolved individually (but chances are a quick AI search will help with that).
Get Dimterion’s stories in your inbox
Join Medium for free to get updates from this writer.
To keep current package versions from your previous package-lock.json, you can run the pnpm import command, and to remove npm artifacts there is another command:
// For macOS/Linux/Git Bash:
rm -rf node_modules package-lock.json
// For Windows PowerShell:
rm -Recurse -Force node_modules, package-lock.jsonIf you want to prevent accidental npm install later, you can enforce pnpm in your project by adding a script to your package.json:
"scripts": {
"preinstall": "npx only-allow pnpm"
}You might need to install this dependency afterwards:
pnpm add -D only-allowIf you want to use the exact pnpm version, you can also add the following line to your package.json (replace 11.22.0 with the version you need):
{
"packageManager": "pnpm@11.22.0"
}The above might be useful when you’re working in a team and you want to prevent issues caused by using different versions (though you have to keep in mind that you’ll need to change the version if you decide to update).
You can also check your current pnpm version and update it with the following commands:
pnpm --version
pnpm self-updateIf you run into update issues, a regular npm installation can be used instead (npm install -g pnpm). You might need to restart your terminal after an update.
After switching to pnpm:
- package-lock.json is removed.
- pnpm-lock.yaml is created.
- package.json remains untouched.
- node_modules remains, but is now managed by pnpm (if it’s been deleted, it can be recreated by a new pnpm install command).
- You can use pnpm instead of npm for your commands (most of them have a pnpm equivalent, so you’re basically changing only one letter in your commands).
- In case you need to run an npx command, you can use pnpm dlx instead.
This was some basic information about using npm and pnpm, their pros and cons, and a few tips on switching to pnpm. Hopefully, this was helpful, and of course documentation is your best friend in case you need to find some additional information.
Thank you for reading.










