Installing Node.js
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against Node.js 26.10.0 (Current, becoming LTS on 2026-10-28), Node.js 24.21.0 "Krypton" (Active
LTS) and Node.js 22.23.3 "Jod" (Maintenance), all checked on 2026-10-03. Every command was run with those three lines.
The only APIs touched are the process.release and process.versions properties (Stable) and the npm engines
field. Installing Node.js is the first step of the Bookshelf application that grows across this section, and the
choices made here (how Node is installed, how its version is pinned) decide whether the same code runs identically on
a laptop, in CI and in a container.
Ways to get Node.js
Node.js is a single executable (node) plus the bundled npm. Every installation route ends with the same two
commands working, which are also the quickest sanity check:
node -v
npm -v
Source: Node.js: Download
On Node.js 26.10.0 they print v26.10.0 and 11.19.1; on 24.21.0 they print v24.21.0 and 11.19.0; on 22.23.3
they print v22.23.3 and 10.9.9. The routes differ in who controls the version and how it is upgraded:
| Route | Good for | Trade-off |
|---|---|---|
Official installer ( |
A single machine-wide Node.js, no tooling to learn. |
One version at a time; upgrades are manual and system-wide. |
Prebuilt binaries (tarball or zip) |
Servers, CI images, air-gapped hosts; you control where the files go. |
You manage |
System package managers (Homebrew, Chocolatey, winget, and similar) |
Fits existing machine provisioning. |
Their packaging is not maintained by the Node.js project; the version you get is what the package ships. |
Version managers (nvm, fnm, Volta, asdf, n) |
Developers who switch between projects on different Node lines. |
Per-user, per-shell installs; not a production deployment mechanism. |
Official Docker images |
Reproducible CI and production runtime. |
You choose a base variant (Debian, slim, Alpine) and own the image updates. |
The Download page of nodejs.org generates the exact snippets for your operating system and lists the installer, standalone binary and package manager variants for each release. It also links the source tarball, nightly builds and the unofficial builds for other platforms.
Installers and prebuilt binaries
The installers are the right choice if you want one Node.js and do not want to manage versions. The prebuilt binaries
are archives you unpack anywhere; Node.js needs no installation step beyond placing bin/node (and npm) on PATH.
Checking a download against the signed checksums is the supported way to establish that the archive is genuine.
curl -fsSLO https://nodejs.org/dist/v{version}/node-v{version}-linux-x64.tar.xz
curl -fsSLO https://nodejs.org/dist/v{version}/SHASUMS256.txt
grep " node-v{version}-linux-x64.tar.xz$" SHASUMS256.txt | sha256sum -c -
Source: Node.js: Download
The {version} placeholders are literal: substitute a real version such as one listed on the releases index. The same
index is available as JSON at https://nodejs.org/dist/index.json, which version managers and CI setup actions read.
System package managers
The Node.js site lists the package-manager routes under its Install Node.js via package manager page. They are
convenient but community-maintained, so the version you receive depends on the package. A Homebrew formula, for
example, is versioned by major line (node@24), which pins the line but not the patch release.
brew install node@24
node -v
On Windows the same page offers Chocolatey (choco install nodejs) and the Windows Package Manager (winget); for
Linux it points to the distribution’s own packages and to the NodeSource and binary-distribution alternatives. Because
distribution packages often lag behind the release lines, check node -v after installing and prefer a version
manager or the official image when you need a specific line.
What node -v and npm -v tell you
Besides the version, the runtime tells you whether you are on a long-term support line. process.release.lts is
the codename on LTS lines and is undefined on a Current line:
node -p "process.version + ' ' + (process.release.lts ?? 'Current')"
node -p "process.versions.v8"
Source: Node.js: process.release
Run on the three lines, the first command printed v26.10.0 Current, v24.21.0 Krypton and v22.23.3 Jod. Node 26
also has no codename yet, because the schedule assigns it when LTS starts. The relation between lines and support
dates is covered on Release Lines & LTS.
Version managers
Different projects pin different Node lines, so developers usually install a version manager and let each project
choose. All of them install under the user’s home directory and switch the active node by changing PATH, so no
administrator rights are needed.
nvm
nvm is a POSIX shell function, so it works in bash, zsh and similar shells (not natively in PowerShell). The Node.js download page shows the install script pinned to an nvm release; the one tested here was nvm 0.40.4.
nvm install 26
nvm install 24
nvm install 22
nvm use 24
nvm ls
nvm alias default 24
Source: Node.js: Download
nvm use with no argument reads a .nvmrc file in the current directory (or a parent). The file holds one version
specifier: a major (24), a full version (24.21.0), or an alias such as lts/* or an LTS codename.
echo 24 > .nvmrc
nvm use
echo lts/jod > .nvmrc
nvm use
Source: Node.js: Download
The two nvm use calls printed Now using node v24.21.0 (npm v11.19.0) and Now using node v22.23.3 (npm v10.9.9).
nvm only reads .nvmrc when asked; it does not switch automatically when you cd, unless you add a shell hook.
fnm and Volta
fnm (Fast Node Manager) is a single binary, so it also runs on Windows natively (winget install Schniz.fnm is the
command shown on the Node.js download page). It reads the same .nvmrc files, and can also read .node-version and the
engines field when configured to. Volta takes a different approach: it installs shims for node, npm and package
binaries and records the pinned versions in package.json under a volta key, so every contributor, and CI, resolves
the same toolchain without a shell function. I did not install fnm or Volta in the scratch environment, so their exact
options are not reproduced here; follow each project’s own documentation for flags.
| Tool | Pin file | Notes |
|---|---|---|
nvm |
|
Shell function; macOS, Linux and WSL; needs a hook for automatic switching. |
fnm |
|
Single binary; Windows, macOS, Linux. |
Volta |
|
Shims; also pins npm and global tools per project. |
asdf, n |
|
General-purpose or minimal managers listed on the Node.js download page. |
Pinning in package.json: engines
A pin file tells a version manager what to install. The engines field in package.json states what the package
supports, and npm checks it. By default a mismatch only prints a warning; with engine-strict=true in .npmrc it
becomes an error.
{
"name": "bookshelf",
"private": true,
"engines": { "node": ">=24.12.0 <27" }
}
Source: npm: package.json, engines
Running npm install under Node 22 with engine-strict=true stopped with npm error code EBADENGINE and
Unsupported engine, listing the required range and the actual versions. Under Node 26 the same install succeeded.
Without engine-strict, Node 22 produced only an EBADENGINE warning and the install went ahead.
engine-strict=true
Source: npm: config, engine-strict
Use the three together: .nvmrc or volta for developers, engines for dependants and installers, and the Docker
base image tag (below) for production. Keep them on the same line, otherwise tests pass on one Node and the container
runs another.
Official Docker images
The Node.js project maintains the node image on Docker Hub. Tags follow node:<version> plus an optional variant:
the default Debian-based image, -slim (fewer packages), -alpine (musl libc, noticeably smaller) and the
Debian-release variants (-bookworm, -trixie). The node:lts tag follows the Active LTS line. Pinning at least the
major, for example node:24-slim, avoids a surprise upgrade; pinning the digest makes the build fully reproducible.
docker run --rm node:26-slim node -p "process.version"
docker run --rm node:24-alpine node -p "process.version"
docker run --rm node:22 node -p "process.version"
These printed v26.10.0, v24.21.0 and v22.23.3, all on linux arm64 (the architecture of the machine used; the
images are multi-architecture). The images ship a non-root user named node (uid 1000), which a production
Dockerfile should select with USER node.
FROM node:24-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY src ./src
USER node
CMD ["node", "src/server.js"]
Alpine images use musl instead of glibc, so native add-ons built for glibc may not run there, and tools such as bash
and git are not included. Use -slim when in doubt. The Docker concepts themselves (layers, multi-stage builds,
registries) are in Docker: Getting Started.
Windows and WSL
On Windows you have two reasonable setups. Native Windows uses the official .msi installer, winget, Chocolatey or
fnm; commands run in PowerShell or Command Prompt and paths use backslashes. Windows Subsystem for Linux (WSL) runs a
real Linux distribution, so everything on this page for Linux applies unchanged, including nvm. Production servers are
almost always Linux, so developing inside WSL removes a class of differences: path separators, file-permission bits,
case-sensitive file names, shell syntax in package.json scripts, and native add-ons.
| Aspect | Native Windows | WSL |
|---|---|---|
Install |
|
Same as Linux: nvm, fnm, distribution packages |
Shell scripts in npm scripts |
Run through |
Run through |
File performance |
Good on |
Keep projects on the Linux filesystem, not under |
Version manager |
fnm or Volta (nvm is a separate Windows project) |
nvm, fnm, Volta |
Keep one Node installation per environment. A Windows node and a WSL node are different programs with different
global packages.
Corepack, pnpm and Yarn
npm is bundled with Node.js. pnpm and Yarn are not. Until Node.js 24, Corepack, a small tool bundled with Node that
provisions the package manager named in the packageManager field of package.json, shipped inside the distribution,
and corepack enable created the pnpm and yarn shims.
Starting with Node.js 25.0.0 (2025-10-15), Corepack is no longer distributed with Node.js. This is a semver-major
build change (the release notes list "stop distributing Corepack"). Node 26 therefore has no corepack command: on
Node 26.10.0, which corepack finds nothing, while on 24.21.0 and 22.23.3 it still resolves from the bundled copy (Corepack
version 0.36.0 on 24.21.0). The Node.js documentation page for Corepack now redirects to the Corepack repository.
| Line | What you get |
|---|---|
Node 22 and 24 |
Bundled |
Node 25 and 26 |
No bundled Corepack. Install it yourself, or install the package manager directly. |
There are two supported ways forward. The first keeps the Corepack workflow and installs Corepack from npm; this is exactly what the Node.js download page now shows:
npm install -g corepack
corepack enable pnpm
pnpm -v
npm install -g corepack installed version 0.36.0 (run here with --prefix into a scratch directory so no global
state changed). With a "packageManager": "pnpm@<version>" field in package.json, the resulting pnpm shim then
runs the pinned version, which is how teams keep every contributor on one package manager version.
The second route skips Corepack and installs the package manager as an ordinary package, or with its own standalone installer:
npm install -g pnpm
npm install -g @yarnpkg/cli-dist
yarn -v
Both installs worked on Node 26; @yarnpkg/cli-dist provided the modern Yarn (4.18.1 on 2026-10-03), whereas the npm
package named yarn is still Yarn Classic (1.22.22). Installing pnpm with npm 11 also printed a warning about
install scripts and the allow-scripts setting; follow the hint printed by npm if the package needs it. Note that pnpm
read the packageManager field of the project it was run in and ran the pinned version, so a lockstep version in
package.json still applies. Which of the two ways to choose is a team decision: Corepack gives per-project version
pinning, direct installs give fewer moving parts. The tools' own installation pages lean towards their preferred routes: on
2026-10-03 the pnpm page offered a standalone installer (npx get-pnpm, which needs Node.js 22.13 or newer) and install scripts rather
than npm install -g pnpm, and the Yarn page recommended installing Corepack with npm install -g corepack and pinning Yarn per
project (yarn init -2, yarn set version stable) rather than a global Yarn.
What changed recently
-
Node.js 25.0.0 (2025-10-15): Corepack is no longer distributed;
corepackmust be installed from npm (see above). Node 25 is end-of-life (2026-06-01). -
Node.js 26 (Current): no codename yet; LTS begins 2026-10-28 and Maintenance 2027-10-20. It bundles npm 11.19.1.
-
npm releases: npm 12 is the
latesttag on the registry (12.2.0) but is not bundled with any Node line, sonpm install -g npm@latestupgrades past what Node ships. Node 22 still ships npm 10.9.9. -
Node.js 24 "Krypton": Active LTS until 2026-10-20, then Maintenance; end-of-life 2028-04-30.
-
Node.js 22 "Jod": Maintenance; end-of-life 2027-04-30. Node 20 reached end-of-life on 2026-04-30.
-
Node.js 27: the first line under the new annual model (alpha from 2026-10-28), where every line becomes LTS.
See Upgrading & What’s Changed for the full list of breaking changes between lines.
Where the books are outdated
The installation chapter of Efficient Node.js by Samer Buna (O’Reilly, 2025) describes installing through the
installer, Homebrew, nvm and WSL, which is still sound, but its release-line guidance predates Node 25 and 26, so check
the dates above. The appendix of Node.js Projects by Jonathan Wexler (O’Reilly, 2025) shows enabling Yarn through
Corepack; on Node 25 and later that command no longer exists until Corepack is installed from npm. Treat any
corepack enable instruction from older material as requiring the extra install step on current Node.