Skip to main content

136. NVM for Node.js Version Management

Status: Accepted Date: 2025-07-06

Context

Different JavaScript and TypeScript projects often have strict requirements for the version of Node.js they run on. Relying on a single version of Node.js installed from the system's package manager (apt) is inflexible and can make it impossible to work on multiple projects with conflicting version needs. This is the same problem we face with Python.

Decision

We will use NVM (Node Version Manager) to manage our Node.js installations, in the same philosophical vein as our use of pyenv for Python (adr://pyenv-version-management).

The 07_nodejs Ansible role is responsible for:

  1. Installing the nvm shell script.
  2. Using nvm to install one or more specific versions of Node.js.
  3. Setting a global default Node.js version via nvm alias default.

This provides a clean, flexible, and isolated way to manage Node.js versions on a per-user basis, completely independent of any system-provided Node.js package.

Consequences

Positive:

  • Version Flexibility: Allows developers to easily install and switch between multiple versions of Node.js to match project requirements. This is essential for our monorepo, which may contain services with different Node.js version targets.
  • Isolation: NVM installs Node.js versions and their associated global packages into a dedicated directory (~/.nvm), keeping them completely isolated from each other and from the system.
  • User-Space Tooling: Treats Node.js as a piece of user-level development tooling, which is its correct place. This prevents system-wide installations that can be hard to manage.

Negative:

  • Requires Shell Integration: NVM is a shell script, not a standalone binary. For it to work, the user's shell configuration (.zshrc, etc.) must be modified to source the nvm.sh script.
  • Slower Provisioning: Installing Node.js via NVM can be slower than installing a pre-packaged binary from apt.

Mitigation:

  • Automated Shell Integration: The required shell integration is a standard part of our dotfiles setup, which is deployed automatically by chezmoi. This is a solved problem within our ecosystem.
  • One-Time Cost: The installation time is a small, one-time cost during initial provisioning. The subsequent benefits of version flexibility and isolation are well worth this cost.