Understand Node.js, nvm, npm, npx, Yarn, and Corepack: Who Does What?

When you start working with modern JavaScript tooling, you immediately run into a bunch of names:

  • Node.js
  • nvm
  • npm
  • npx
  • Yarn
  • Corepack

Docs casually say things like:

  • “Install Node with nvm”
  • “Use npm or Yarn to install dependencies”
  • “Run the generator with npx”
  • “Use Corepack with Yarn 4”
  • “Backstage recommends Yarn + Corepack”

If you only want to run a project or set up something like Backstage, this can feel unnecessarily complicated.

This post is a relationship map:

  • What each tool actually is
  • How they relate to each other
  • Which pieces you really need
  • How to combine nvm + Node + npm + Yarn + Corepack in a sane way

  1. Big Picture: Who Manages What?

If you remember only one thing, remember this:

There are layers.
nvm manages Node versions.
Each Node version ships with npm and npx. Newer Node versions also ship with Corepack.
Corepack manages Yarn/pnpm versions.
npm / Yarn / pnpm manage your actual packages.

A quick summary table:

NameTypeMain RoleTypical Commands
nvmNode version managerInstall and switch between Node versionsnvm install 22, nvm use --lts
Node.jsRuntimeRun JavaScript/TypeScript outside the browsernode app.js
npmPackage managerInstall and manage Node packagesnpm install, npm install -g typescript
npxCLI runner (uses npm under the hood)Download and execute CLI tools on demandnpx @backstage/create-app@latest
YarnPackage managerAlternative to npm; often used in modern toolchainsyarn install, yarn dev, yarn build
CorepackPackage-manager managerShip and pin Yarn/pnpm versions per projectcorepack enable, then just yarn / pnpm

  1. Hierarchy View: Like Expanding Folders in a File Explorer

An easy way to visualize the relationships is to imagine a file explorer tree.

Conceptually:

nvm
├─ Node v18.x
│  ├─ npm
│  │  ├─ Global packages (for Node v18.x)
│  │  │  ├─ typescript
│  │  │  └─ eslint
│  │  └─ Project packages (per-project node_modules)
│  │     ├─ /project-a/node_modules
│  │     └─ /project-b/node_modules
│  ├─ npx
│  │  └─ CLI runs (each maps to some package@version)
│  │     ├─ npx @backstage/create-app@latest
│  │     └─ npx create-react-app@5
│  └─ Corepack
│     ├─ yarn@4.5.0  (for Project A, from packageManager)
│     │  └─ Packages installed via Yarn in Project A
│     ├─ yarn@4.4.1  (for Project B)
│     │  └─ Packages installed via Yarn in Project B
│     └─ pnpm@9.x    (for any project using pnpm)
│        └─ Packages installed via pnpm
│
└─ Node v22.x
   ├─ npm
   ├─ npx
   └─ Corepack
      └─ (its own Yarn/pnpm versions & caches)

In words:

  • nvm expands into multiple Node versions (v18, v20, v22, …).
  • Each Node version expands into:
    • npm – manages packages (global + per-project)
    • npx – runs CLI tools (mapping to specific packages/versions)
    • Corepack – manages concrete Yarn/pnpm versions
  • Corepack expands into:
    • yarn@4.5.0, yarn@4.4.1, pnpm@9.x, …
  • Each specific Yarn/pnpm version expands into:
    • The packages it installs for the projects that use it.

So the hierarchy is:

nvm → Node versions → npm / npx / Corepack →
Corepack → Yarn / pnpm versions → dependencies in each project.

Note: In reality, when you run which yarn, you’ll see a single path like
~/.nvm/versions/node/v20.19.6/bin/yarn.
That file is a Corepack shim, not “the Yarn binary itself”. Corepack uses that shim to dispatch to different Yarn versions (e.g. yarn@4.5.0, yarn@4.4.1) depending on what each project declares in its packageManager field.

With this picture in mind, the rest of the details become easier to digest.


  1. nvm: Node Version Manager (and How to Install It)

We start at the top of the tree: nvm.

What nvm Does

nvm (Node Version Manager) is not part of Node. It’s a separate tool that:

  • Installs Node into ~/.nvm/versions/node/...
  • Lets you easily install multiple Node versions
  • Lets you switch Node versions in your shell
  • Keeps “global” npm installs isolated per Node version

Typical commands:

# Install specific Node versions
nvm install 22
nvm install --lts           # latest LTS
nvm install --lts=iron      # specific LTS codename

# Switch version in current shell
nvm use 22
nvm use --lts

# Set default Node for new shells
nvm alias default 22
nvm alias default --lts

With nvm:

  • npm install -g installs inside the currently active Node version’s directory.
  • node -v and npm -v change when you run nvm use ....

In the file-explorer analogy:

nvm
├─ Node v18.x
└─ Node v22.x

Key idea:

nvm sits at the top. It decides which Node version (and therefore which npm/npx/Corepack instance) your shell is using.

Installing nvm (Quick)

You can install nvm with the official install script, for example:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash

Then reload your shell config (depending on what you use):

# For Bash
source ~/.bashrc

# For Zsh
source ~/.zshrc

Verify that nvm is available:

nvm --version

From here on, all Node-related commands in this post assume you have nvm working.


  1. Node.js: The Runtime Inside Each nvm Node

Under each Node version folder in that tree, you have Node.js itself.

Node.js is the runtime that executes JavaScript (and transpiled TypeScript) outside the browser.

  • Embeds the V8 engine (from Chrome).
  • Provides server-side APIs like fs, http, net, etc.
  • When installed via nvm, each version lives in its own directory and comes with:
    • npm – the default package manager.
    • npx – the CLI runner (bundled with npm).
    • Corepack – in newer Node versions, for Yarn/pnpm management.

Example:

node app.js

This runs a JavaScript file with the currently active Node version (selected by nvm).

Within the tree:

nvm
└─ Node v22.x
   ├─ node (the runtime)
   ├─ npm
   ├─ npx
   └─ Corepack

From here down, everything you do (installing packages, running CLIs, using Yarn via Corepack) happens inside the context of this Node version.


  1. npm: The Default Package Manager

npm is the default package manager that comes bundled with Node.

It has two main jobs:

  • Install dependencies into your project
  • Install CLI tools (locally for the project, or “global” per Node version)

Common patterns:

# Local (project-level) install – creates node_modules/ in this directory
npm install                 # read package.json dependencies
npm install lodash          # add lodash to dependencies

# Global install (scoped to current Node version when using nvm)
npm install -g typescript
tsc --version

Where things go:

  • Local install → ./node_modules and ./node_modules/.bin
  • Global install (with nvm) →
    ~/.nvm/versions/node/vXX.YY.ZZ/lib/node_modules/...
    plus symlinks in ~/.nvm/versions/node/vXX.YY.ZZ/bin

In the tree:

Node v22.x
└─ npm
   ├─ Global packages
   │  ├─ typescript
   │  └─ eslint
   └─ Project packages
      ├─ /project-a/node_modules
      └─ /project-b/node_modules

So with nvm:

  • You do not pollute system-wide directories like /usr/local/lib/node_modules.
  • “Global” npm tools are tied to that Node version.

  1. npx: “Download and Run This CLI Once”

npx is a CLI runner built on top of npm.

Instead of:

npm install -g some-cli
some-cli init

you can run:

npx some-cli init

What happens when you run npx some-cli:

  • Look for some-cli in:
    • local node_modules/.bin
    • global npm installs for the current Node version
  • If not found, download some-cli from the npm registry to a cache
  • Run its bin script once
  • You don’t keep it as a permanent global install

Example with Backstage:

npx @backstage/create-app@latest

This:

  • Downloads @backstage/create-app (if necessary)
  • Runs its CLI to scaffold a new Backstage app
  • You don’t have to npm install -g @backstage/create-app

In the tree:

Node v22.x
└─ npx
   └─ CLI runs (mapped to package@version)
      ├─ npx @backstage/create-app@latest
      └─ npx create-react-app@5

Key idea:

npm is for installing packages.
npx is for executing CLI packages on demand (often without global install).


  1. Yarn: An Alternative Package Manager

Yarn is a package manager for Node projects, originally created to improve npm’s weaknesses in speed and determinism.

Key points:

  • Reads package.json like npm.
  • Uses its own lockfile (yarn.lock).
  • Commands are similar but not identical:
# Install dependencies
yarn install

# Add dependencies
yarn add lodash
yarn add --dev typescript

# Run scripts from package.json
yarn dev
yarn build
yarn test

Two important “eras” of Yarn:

  • Yarn 1 (“Classic”) – more like a traditional npm alternative.
  • Yarn 2+ (Berry, v3, v4, …) – modern architecture, more features (Plug’n’Play, etc.), different behavior in some areas.

Many modern toolchains (including Backstage) expect Yarn Berry (v3/v4), not Yarn 1.

Historically people installed Yarn globally:

npm install -g yarn
yarn -v

With Corepack, that’s no longer the preferred default.


  1. Corepack: Manager for Yarn and pnpm

Corepack is bundled with newer Node versions. Its job is to manage other package managers, such as:

  • Yarn
  • pnpm

Its goals:

  • Avoid manual global installs like npm install -g yarn.
  • Use the exact package manager version that the project asks for.

Projects can declare their package manager in package.json:

{
  "name": "my-app",
  "version": "1.0.0",
  "packageManager": "yarn@4.5.0"
}

With Corepack enabled, when you run yarn inside this project:

  • Corepack reads "packageManager": "yarn@4.5.0".
  • If it doesn’t have Yarn 4.5.0 yet, it downloads and caches it.
  • It runs Yarn 4.5.0 to handle commands for this project.

You don’t manually install Yarn at all.

Basic Corepack usage:

# Enable shims for yarn / pnpm (once per Node version)
corepack enable

# (Optional) Pre-fetch a Yarn version for general use:
corepack prepare yarn@stable --activate

After corepack enable, the yarn you see from which is the Corepack shim:

which yarn
# /home/ubuntu/.nvm/versions/node/v20.19.6/bin/yarn

That path is just the launcher. Corepack uses it to decide which Yarn version to run based on the current project:

  • In a project with "packageManager": "yarn@4.5.0"yarn -v shows 4.5.0
  • In another project with "packageManager": "yarn@4.4.1"yarn -v shows 4.4.1

Same which yarn, different Yarn versions behind the scenes.

Important:

Corepack does not manage npm. npm is still bundled directly with Node.

Did this guide save you time?

Support this site

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top