Instalar o Node.js com nvm e trocar de versão por projeto
Instalar o nvm no Linux, macOS e Windows, fixar a versão do projeto com .nvmrc e resolver o command not found que aparece depois de instalar.
O nvm guarda várias versões do Node.js no seu computador e deixa você escolher,
por pasta, qual delas responde pelo comando node. É por isso que ele é a forma
recomendada de instalar o Node: um comando troca a versão inteira, e um arquivo
de uma linha registra qual versão o projeto usa.
Os exemplos aqui são de uma escola de idiomas, a Escola Aurora, que tem um script de relatório de matrículas. O mesmo script vai rodar em uma versão e quebrar em outra — e é isso que faz o nvm valer a pena.
O nvm é um gerenciador de versões. Em palavras simples, ele mantém várias
instalações do Node separadas e troca qual executável aparece quando você roda
node, sem obrigar todos os projetos a usar o mesmo número.
A gaveta de ferramentas de cada projeto
Numa oficina, duas máquinas podem exigir chaves do mesmo formato em tamanhos
diferentes. Jogar fora uma chave toda vez que muda de máquina cria trabalho e
erro; uma gaveta identificada permite pegar a medida certa. O nvm é a gaveta, a
versão do Node é a ferramenta e o .nvmrc é a etiqueta deixada pelo projeto.
Antes e depois de cada nvm use, rode os comandos de versão mostrados na lição
e anote o caminho do executável. A microprática confirma duas mudanças: o número
respondido por node e o binário que o shell encontrou. Assim você não depende
apenas da mensagem de sucesso do nvm.
Quando você baixa o Node em nodejs.org e roda o instalador, o node vai para
uma pasta do sistema. Existe um Node na máquina, e trocar de versão significa
desinstalar e instalar de novo.
Isso funciona enquanto você tem um projeto. Some no dia em que você tem dois: o site da escola roda em Node 18 porque a hospedagem é antiga, e a API nova roda em Node 24 porque usa recursos que o 18 não tem. Com um Node global, um dos dois está sempre quebrado.
O nvm resolve por um caminho simples: ele não instala o Node no sistema. Instala
tudo dentro de uma pasta sua, e mexe no PATH do terminal para apontar para a
versão que você escolheu. Trocar de versão é mudar o PATH, o que leva
milissegundos e não pede senha de administrador.
Instalando o nvm no Linux e no macOS
O instalador é um script. Você baixa e executa numa linha:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bashFeche o terminal e abra de novo — esse passo não é opcional, e a próxima seção explica por quê. Agora confira que o nvm respondeu:
nvm --version
nvm ls-> system * iojs -> N/A (default) node -> stable (-> N/A) (default) unstable -> N/A (default)
Repare que nenhum Node foi instalado ainda. O nvm é só o gerenciador; o
system que aparece ali é o Node que já existia na máquina, fora do controle
dele. Instalar a versão de longo suporte é o segundo comando:
nvm install --lts(As linhas da barra de progresso foram retiradas.) A última linha é a parte que
importa: o nvm criou o apelido default, que é a versão que todo terminal novo
vai usar.
Agora as outras duas versões da Escola Aurora:
nvm install 18.20.8
nvm install 22Você pediu 22 sem o resto e o nvm completou sozinho para v22.23.2, a mais
nova daquela linha. Vale para nvm install 18, nvm use 20 e por aí vai.
nvm ls agora mostra o inventário completo. A seta marca a versão ativa — e ela
está no 24 porque este nvm ls rodou num terminal novo, que abre sempre no
default:
nvm lsAs três primeiras linhas são as versões que o nvm baixou; a quarta, system, é o
Node que já estava na máquina. Da quinta em diante são apelidos.
Aquelas palavras esquisitas — hydrogen, jod, krypton — são os codinomes das
linhas de LTS, e nvm use lts/jod funciona igual a nvm use 22. Os apelidos
seguidos de N/A existem, mas apontam para versões que você não baixou.
Windows: outro programa, quase os mesmos comandos
O nvm é um script de shell. No Windows nativo ele não roda. Existem duas saídas, e as duas são legítimas:
| caminho | como instalar | lê .nvmrc |
precisa de administrador |
|---|---|---|---|
| WSL (Ubuntu no Windows) | o mesmo curl da seção acima, dentro do WSL |
sim | não |
| nvm-windows | winget install CoreyButler.NVMforWindows |
não | sim, terminal como admin |
Com o nvm-windows, os comandos do dia a dia mudam pouco:
nvm install 24.19.0
nvm use 24.19.0
nvm listTrês diferenças que pegam gente: não existe nvm install --lts (você digita o
número), nvm use não lê o .nvmrc da pasta, e o terminal precisa estar
aberto como administrador porque o nvm-windows troca a versão mexendo num link
simbólico dentro de Program Files.
Se você vai trabalhar com back-end de verdade no Windows, o WSL é o caminho mais tranquilo: é o mesmo Linux que roda no servidor, com os mesmos comandos deste artigo.
LTS ou Current: qual número entra no projeto
O Node lança uma versão nova a cada seis meses. As de número par viram LTS (long-term support) e ganham correção por cerca de trinta meses. As de número ímpar são Current: servem para experimentar recurso novo e saem de suporte em seis meses.
Para ver o que existe de LTS:
nvm ls-remote --lts | tail -8A regra é curta: o projeto roda a mesma versão que a produção
roda. Se a hospedagem da escola está em Node 22, o .nvmrc diz 22, mesmo que
o 24 já exista. Versão diferente entre a sua máquina e o servidor é a origem
clássica do “na minha máquina funciona”.
Você pode registrar essa exigência no package.json, e o npm passa a avisar:
{
"name": "escola-aurora",
"type": "module",
"engines": { "node": ">=22" },
"packageManager": "pnpm@10.4.1",
"scripts": {
"relatorio": "node matriculas.mjs"
}
}Rodando npm install com o Node 18 ativo:
up to date in 468ms
É aviso, não erro: o npm instala mesmo assim. O engines documenta a
intenção; quem garante a versão é o .nvmrc. O "type": "module" que aparece
logo acima é outra decisão de versão disfarçada — ele escolhe entre import e
require, e está explicado em
ESM ou CommonJS no Node.
Fixando a versão do projeto no .nvmrc
O .nvmrc é um arquivo de uma linha, na raiz do projeto, com a versão. Você não
precisa criar na mão:
nvm use --save 24.19.0
cat .nvmrcA partir daí, nvm use sem argumento nenhum lê o arquivo. Estando no Node 18 e
entrando na pasta da escola:
node -v
nvm use
node -vEsse arquivo vai para o Git. É ele que diz para a próxima pessoa — e para você daqui a seis meses — em que versão este projeto foi escrito.
E se o .nvmrc pedir uma versão que a máquina não tem? O nvm avisa e ensina a
saída:
nvm useYou need to run nvm install to install and use the node version specified in .nvmrc.
nvm installOu seja: nvm install também lê o .nvmrc. Ao clonar um projeto novo, os dois
primeiros comandos são sempre nvm install e depois o instalador de pacotes.
Cada versão traz o próprio npm — e os próprios globais
Trocar de Node não muda só o node. Muda o npm junto:
for v in 18 22 24; do nvm use $v > /dev/null; echo "node $(node -v) npm v$(npm -v)"; doneE muda também onde os pacotes globais moram:
nvm use 18 > /dev/null && npm root -g
nvm use 24 > /dev/null && npm root -gCaminhos diferentes, pastas diferentes. Um npm install -g feito no Node 24
simplesmente não existe no Node 18 — e é aí que aparece o
Cannot find module mais frustrante de
diagnosticar, porque o pacote está instalado, só que na outra versão. Por isso
npx costuma ser melhor que instalar global.
A mesma pasta, o mesmo script, duas versões
Agora a prova de que isso não é teoria. O relatório de matrículas da escola usa
Object.groupBy, que chegou ao Node na versão 21:
const matriculas = [
{ aluno: 'Ana Prado', turma: 'ingles-b1', mensalidade: 320 },
{ aluno: 'Bruno Sales', turma: 'espanhol-a2', mensalidade: 280 },
{ aluno: 'Carla Reis', turma: 'ingles-b1', mensalidade: 320 },
{ aluno: 'Diego Luz', turma: 'ingles-a1', mensalidade: 260 },
];
const porTurma = Object.groupBy(matriculas, (m) => m.turma);
for (const [turma, alunos] of Object.entries(porTurma)) {
const total = alunos.reduce((soma, m) => soma + m.mensalidade, 0);
console.log(`${turma}: ${alunos.length} aluno(s), R$ ${total}`);
}Com o Node 24 ativo:
nvm use 24 > /dev/null
node -v
node matriculas.mjsMesma pasta, mesmo arquivo, trocando só a versão:
nvm use 18 > /dev/null
node -v
node matriculas.mjsTypeError: Object.groupBy is not a function at file:///private/tmp/escola-aurora/matriculas.mjs:8:25 at ModuleJob.run (node:internal/modules/esm/module_job:195:25) at async ModuleLoader.import (node:internal/modules/esm/loader:337:24) at async loadESM (node:internal/process/esm_loader:34:7) at async handleMainPromise (node:internal/modules/run_main:106:12)
Node.js v18.20.8
O erro não é do seu código. É o Node 18 dizendo que Object.groupBy não existe
naquela versão do motor. A última linha do stack trace é o que resolve o caso em
dois segundos: Node.js v18.20.8. Sempre leia essa linha antes de sair mexendo
no código — como em qualquer
erro de JavaScript, a mensagem já
traz o diagnóstico.
Opções de linha de comando também nascem numa versão. O --run, que executa um
script do package.json sem passar pelo npm, chegou no Node 22:
nvm use 24 > /dev/null && node --run relatorio
nvm use 18 > /dev/null && node --run relatorionvm: command not found depois de fechar o terminal
Este é o problema número um de quem acabou de instalar. Você instala, funciona, fecha o terminal, abre de novo e:
nvm lsNão é instalação corrompida. O nvm não é um programa — é uma função de shell que precisa ser carregada em cada terminal que abre. Num terminal em que ele está funcionando, dá para confirmar isso:
which nvm
echo "codigo de saida: $?"
type -t nvmwhich não achou nada (código de saída 1) porque não existe arquivo nvm em
lugar nenhum do PATH. Já type -t responde function. O instalador tenta
escrever a linha que carrega essa função no seu arquivo de perfil; quando ele não
encontra o arquivo, ou quando você usa um shell que ele não previu, nada é
escrito e o command not found aparece.
A correção é acrescentar estas três linhas ao fim do ~/.zshrc (macOS e quem usa
zsh) ou do ~/.bashrc (a maioria das distribuições Linux):
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"Depois, source ~/.zshrc ou feche e abra o terminal.
O apelido default decide a versão de cada terminal novo, e ele não muda o
terminal que já está aberto:
nvm alias default 22
nvm currentO apelido virou 22, mas a sessão atual continua no 24. O próximo terminal é que abre no 22.
corepack: pnpm e yarn sem instalar nada global
Se o projeto da escola usa pnpm ou yarn, você não precisa de npm install -g
nenhum. O Node já vem com o corepack, que lê o campo packageManager do
package.json e baixa exatamente aquela versão:
corepack enable
pnpm -vO 10.4.1 não foi escolha do corepack: é o "packageManager": "pnpm@10.4.1" do
package.json que você viu acima. Todo mundo do time roda a mesma versão do
gerenciador, sem combinar nada — a mesma ideia do .nvmrc, uma camada acima.
Só lembre que o corepack enable cria os atalhos dentro da versão ativa, como
qualquer global. Instalou um Node novo com o nvm? Rode o corepack enable de
novo nele.
O que vem depois
Com o nvm instalado, o .nvmrc no repositório e o terminal carregando a função
em toda sessão, o ambiente está pronto. O próximo passo é entender o que o Node
faz com o seu arquivo: comece por
o que é o Node.js se você ainda não leu, siga para
npm e package.json para instalar a primeira
dependência e veja a ordem completa no
guia de Node.js. A
trilha de Node mostra onde cada assunto entra.
Perguntas frequentes
Preciso desinstalar o Node que eu já tinha antes de usar o nvm?
system e volta a valer sempre que o nvm não estiver carregado. Desinstalar evita horas de confusão.O nvm funciona no Windows?
.nvmrc sozinho e precisa de terminal como administrador.Cada versão do Node tem os próprios pacotes globais?
npm root -g aponta para uma pasta dentro da versão ativa, então um pacote instalado com -g no Node 24 não existe no Node 18. Trocou de versão, reinstale o global ou use npx.Qual versão do Node eu coloco num projeto novo?
Dúvidas e comentários
Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.
Entrar para perguntarÉ o mesmo login gratuito dos cursos.
Nenhuma dúvida por aqui ainda — a primeira pode ser a sua.
Todo o código deste artigo foi executado em nvm 0.40.3 com Node 18.20.8, 20.20.2, 22.23.2 e 24.19.0 no macOS ARM, e as saídas exibidas são as reais — como produzimos este conteúdo.
Fontes consultadas
- nvm — Node Version Manager (repositório oficial) — github.com
- Node.js — Releases e calendário de suporte — nodejs.org
- nvm-windows — Node Version Manager para Windows — github.com


