pnpmnpmFrontend

Replacing npm with pnpm: A Complete Migration Guide

Migrate from npm to pnpm without breaking CI. Update lockfiles, install commands, dependency layout assumptions, hoisting fallbacks, and team workflow.

·Updated ·7 min·Counting...
Replacing npm with pnpm: A Complete Migration Guide

Moving from npm to pnpm is usually simple at the command level and easy to get wrong at the workflow level. The real migration is not just pnpm install; it is also changing the lockfile, the CI commands, and your team’s assumptions about dependency layout.

If you are considering switching from npm to pnpm, this guide covers the practical steps and the most common issues you may hit.


1. Install pnpm

If you currently use npm, the first step is to make sure pnpm is available. There are a couple of common ways to install it.

Install with Homebrew

On macOS:

brew install pnpm

If you already have it installed and just want the latest version:

brew upgrade pnpm

Install with npm

If you do not use Homebrew, install it globally through npm:

npm install -g pnpm@latest-10

The current pnpm installation docs also recommend Corepack as a first-class option and call out the Node.js version requirements for newer releases.


2. Switch an existing project from npm to pnpm

After moving to pnpm, the old node_modules directory and package-lock.json file should be replaced by pnpm's own dependency model.

Step 1: remove node_modules and package-lock.json

rm -rf node_modules package-lock.json

Step 2: reinstall everything with pnpm

pnpm install

This creates a new pnpm-lock.yaml file and rebuilds your dependencies using pnpm's structure.


3. Configure pnpm

If you previously had dependency resolution problems under npm, pnpm offers a config called shamefully-hoist, which can make dependency layout behave more like npm by hoisting packages to the top-level node_modules.

That is useful when some packages incorrectly assume that dependencies live directly in the root node_modules.

Enable it like this:

pnpm config set shamefully-hoist true

This can solve compatibility problems, though you should only turn it on if you actually need it. In practice, hoisting should be a compatibility fallback, not the default target state.


4. Running scripts with pnpm

Your package.json scripts do not need to change. pnpm is compatible with npm script definitions, so a scripts section like this still works:

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  }
}

The only change is the command you type:

  • start the dev server: pnpm run dev
  • build the project: pnpm run build
  • run ESLint: pnpm run lint
  • preview the build: pnpm run preview

5. Cleanup and troubleshooting

If installs hang or behave strangely, cache or disk space issues are often involved. These commands help.

Clean the pnpm store

pnpm store prune

Check disk space

pnpm uses a global store and creates dependency directories on disk. If storage is tight, installs can fail or get stuck. Check available space with:

df -h

6. Common migration problems

Problem 1: install hangs

Possible causes include cache problems, low disk space, or network issues.

Try:

pnpm store prune
rm -rf node_modules pnpm-lock.yaml
pnpm install

Problem 2: dependencies are not resolved correctly

If some packages cannot find what they need, confirm whether shamefully-hoist should be enabled. If necessary, delete node_modules and reinstall.

Problem 3: permission errors

On macOS or Linux, install commands can fail because of permission problems. Make sure you have the required permissions, or use a safer environment setup rather than blindly adding sudo everywhere.

Problem 4: CI still runs npm

This is a common half-migration. If the repository now commits pnpm-lock.yaml, your CI should stop running npm install and switch to pnpm as well.


Summary

Moving from npm to pnpm is usually straightforward, especially because pnpm keeps compatibility with standard npm scripts.

A clean migration usually looks like this:

  1. install pnpm
  2. remove node_modules and package-lock.json
  3. run pnpm install
  4. enable shamefully-hoist only if needed
  5. run your scripts and verify the project works

Once you switch, you usually get faster installs, better cache reuse, and lower disk usage.

If anything goes wrong, the fixes are usually simple: clean the store, reinstall, and check whether your project depends on npm-style hoisting behavior.

If you want the broader tradeoff discussion rather than the migration path, read pnpm vs npm vs yarn. If this is part of a brand-new machine bootstrap, pair it with mac-setup-2026.

What to check before merging

Do not merge a package-manager migration after only running pnpm install. A useful review checklist is:

  1. The old lockfile is removed and pnpm-lock.yaml is committed.
  2. CI installs dependencies with pnpm, not npm.
  3. Local scripts still work: dev, build, lint, test, preview, and any codegen tasks.
  4. Dockerfiles, deployment scripts, and README commands no longer mention npm unless intentionally supported.
  5. The team knows whether Corepack, Homebrew, or a pinned pnpm version is the standard installation path.

The most common failure is a partial migration: the repository has a pnpm lockfile, but CI or deployment still runs npm install. That creates a different dependency graph from the one developers tested locally.

When to postpone the migration

Postpone the switch if you are already in the middle of a risky release, if the project has fragile legacy dependencies, or if the deployment platform is controlled by another team and still assumes npm. The migration is worth doing, but it should be reviewed like infrastructure, not like a formatting change.

For a small project, a single pull request is fine. For a monorepo, migrate in a branch, run every package's test and build script, and document any shamefully-hoist exceptions so they do not become mysterious permanent settings.

After the migration, keep both the package-manager choice and the Node version visible in the repository. A short README note plus packageManager in package.json prevents future contributors from accidentally recreating a second lockfile.

Subscribe to FreeMac

Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.