Alternative Package Managers

npm is the default, but it is not the only option. Two other package managers are widely used: Yarn and pnpm. They differ from npm in speed, in how much disk space they use, and in the workflow features they provide. All three install packages from the same npm registry, so switching between them is mostly a matter of tooling preference.

Managing Packages with Yarn

Yarn was originally written at Facebook to fix performance and reliability problems in early versions of npm.

# Preferred on modern Node.js: use Corepack
corepack enable
corepack prepare yarn@stable --activate

# (Alternative) install globally
# npm install -g yarn

# Initialize a project
yarn init

# Install all dependencies from package.json
yarn install

# Add a production dependency
yarn add lodash

# Add a development dependency
yarn add --dev jest

# Remove a package
yarn remove lodash

# Run scripts (no "run" keyword needed)
yarn dev
yarn test

Yarn uses yarn.lock as its lock file. Yarn v2 and later also has a feature called Plug’n’Play (PnP). It removes the node_modules folder entirely and resolves packages through a generated .pnp.cjs file instead. That can make installs much faster, but not every package works with it.

Efficient Installs with pnpm

pnpm (performant npm) stores packages differently from the other two. Instead of copying packages into each project’s node_modules, it keeps them in a global content-addressable store and creates hard links into the project. If ten projects use the same version of lodash, it is stored on disk only once.

# Preferred on modern Node.js: use Corepack
corepack enable
corepack prepare pnpm@latest --activate

# (Alternative) install globally
# npm install -g pnpm

# Commands mirror npm closely
pnpm install
pnpm add lodash
pnpm add -D jest
pnpm remove lodash
pnpm run dev

pnpm uses pnpm-lock.yaml as its lock file. pnpm also enforces strict dependency isolation. Your code can only import packages that are listed in package.json. This catches “phantom dependencies”, which are common in hoisted node_modules setups.

Comparing npm, Yarn, and pnpm

Feature npm Yarn pnpm
Lock file package-lock.json yarn.lock pnpm-lock.yaml
Disk usage Moderate Moderate Efficient (shared store)
Install speed Good Good Fast (often fastest)
Workspaces Yes Yes Yes
Plug’n’Play No Yes (v2+) No
Strict isolation Limited by default Yes (with PnP) Yes

For most projects, any of these will work well. npm is the safe default since it comes with Node.js. My advice is to pick one and be consistent across your team.

Monorepos and Workspaces

When a project grows large enough, you might split it into multiple packages that live in one repository – this is called a monorepo. All three package managers support workspaces for this pattern:

{
  "name": "my-monorepo",
  "workspaces": ["packages/*"]
}
my-monorepo/
  package.json
  packages/
    shared/
      package.json
    web-app/
      package.json
    api/
      package.json

Workspaces let you install dependencies for all sub-packages at once and link them together so they can import from each other during development.

Best Practices for Dependency Management

  1. Commit your lock file – it ensures reproducible builds across machines.
  2. Audit regularly – run npm audit (or the equivalent) to catch known vulnerabilities.
  3. Keep dependencies updated – use npm outdated to spot stale packages before they become a problem.
  4. Minimize your dependency count – every package you add is code you do not control. Fewer dependencies mean a smaller attack surface and less maintenance.
  5. Use devDependencies correctly – test runners, linters, and build tools should never ship to production.
  6. Pin versions for critical apps – consider exact versions (no ^ or ~) for production deployments where stability matters.