O que é o npm, na prática
O npm é, na verdade, três coisas reunidas sob o mesmo nome. É um registro — um enorme banco de dados público de pacotes JavaScript hospedado em npmjs.com. É uma ferramenta de linha de comando que vem junto com o Node.js e serve para instalar e gerenciar esses pacotes. E é também uma especificação (o formato package.json) que descreve o que um projeto precisa para funcionar.
Quando você roda npm install express, a CLI conversa com o registro, baixa o express e todas as suas dependências, joga os arquivos em uma pasta chamada node_modules e registra o pacote junto com sua versão no seu package.json. É esse o ciclo todo.
Se você já tem o Node.js instalado, o npm também já está aí. Para conferir:
node --version
npm --version
Se os dois imprimirem uma versão, você está pronto para seguir.
Começando um projeto: npm init
Todo projeto npm precisa de um package.json. Esse é o manifesto do projeto — ele guarda o nome, a versão, os scripts e as dependências. O jeito mais rápido de criar esse arquivo é rodar npm init -y, que aceita todos os valores padrão:
mkdir my-app
cd my-app
npm init -y
Algo parecido com isto será exibido:
{
"name": "my-app",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Se você omitir o -y, o npm pergunta cada campo interativamente. De qualquer jeito, no final você fica com um package.json — o arquivo em que todo o resto se apoia. Vamos detalhar os campos dele na próxima página.
Como instalar um pacote com npm install
Com o package.json em mãos, instale um pacote usando npm install (ou npm i, na forma curta):
npm install lodash
Três coisas acontecem:
- O npm baixa o
lodashe suas dependências para dentro da pastanode_modules/. - Adiciona
"lodash": "^4.17.21"(ou a versão mais recente no momento) na seçãodependenciesdopackage.json. - Cria um arquivo
package-lock.jsonque registra as versões exatas de cada pacote da árvore de dependências.
Pronto, agora é só usar:
A chamada require (ou import, se o projeto usa ESM) localiza o pacote olhando dentro de node_modules. Você não precisa informar o caminho — quem cuida disso é o próprio resolver de módulos do Node.
dependencies vs devDependencies
Nem todo pacote precisa estar presente quando a aplicação roda em produção. Frameworks de teste, linters e bundlers só fazem sentido durante o desenvolvimento. Para esses casos, instale com --save-dev (ou -D):
npm install --save-dev jest
npm install -D eslint prettier
Esses ficam em devDependencies, e não em dependencies:
{
"dependencies": {
"lodash": "^4.17.21"
},
"devDependencies": {
"jest": "^29.7.0",
"eslint": "^8.57.0",
"prettier": "^3.2.5"
}
}
Em um servidor de produção, npm install --omit=dev pula a seção de dev por completo, deixando a instalação menor e mais rápida. Acertar essa separação importa mais do que parece — um webpack parado nas dependencies por engano infla cada deploy de produção.
Instalando tudo de uma vez
Quando você clona um repositório que já tem um package.json, não precisa listar cada pacote. Basta rodar:
npm install
Sem nenhum argumento, o npm lê o package.json (respeitando as versões exatas travadas no package-lock.json) e instala a árvore inteira de dependências dentro de node_modules. É sempre o primeiro comando que você roda ao clonar um projeto.
E é justamente por isso que node_modules precisa estar no .gitignore. Ele é reconstruído a partir do lockfile, ocupa um espaço absurdo e muda toda vez que alguém roda npm install. O que você versiona são o package.json e o package-lock.json — cada dev gera o próprio node_modules na máquina.
Atualizando pacotes
O comando npm outdated mostra o que está desatualizado:
npm outdated
Na tabela, você vai ver as colunas Current, Wanted e Latest. Wanted é a versão mais nova permitida pelo intervalo definido no package.json (para ^4.17.21, qualquer coisa abaixo de 5.0.0). Já Latest é a versão mais recente publicada, que pode ser uma major release que você ainda não liberou.
Para atualizar respeitando o intervalo permitido:
npm update
Para pular direto pra última versão, incluindo mudanças de versão major, basta instalar o pacote de novo usando @latest:
npm install lodash@latest
Mudanças de versão major podem quebrar seu código — é justamente isso que o número de versão está sinalizando. Antes de atualizar cruzando uma major, dá uma olhada no changelog.
Desinstalando pacotes
Remover um pacote segue a mesma lógica:
npm uninstall lodash
Isso remove o pacote do node_modules e apaga a entrada do package.json. Se era uma dependência de desenvolvimento, acrescente -D (o npm normalmente identifica sozinho, mas deixar explícito evita dor de cabeça em scripts).
Instalação global vs local
Na prática, quase toda instalação deve ser local — presa a um projeto, dentro do node_modules dele. A exceção fica por conta das ferramentas de linha de comando que você quer ter disponíveis em qualquer lugar do sistema:
npm install -g typescript
npm install -g http-server
Instalar um pacote globalmente coloca a ferramenta num local do sistema e adiciona o bin correspondente ao seu PATH, fazendo com que você consiga rodar tsc ou http-server de qualquer diretório. O problema é que instalações globais não ficam registradas por projeto e acabam ficando desalinhadas entre máquinas diferentes.
Para comandos pontuais, uma saída mais equilibrada é usar o npx, que já vem junto com o npm:
npx create-react-app my-app
npx prettier --write .
O npx executa um pacote sem precisar instalar globalmente — ele baixa na hora, roda, e pronto. Pra ferramentas que você usa de vez em quando, isso fica bem mais limpo do que manter uma instalação global permanente.
Colinha rápida dos comandos essenciais
Os comandos que você vai usar de verdade no dia a dia:
npm init -y # cria package.json
npm install # instala tudo que está em package.json
npm install <pkg> # adiciona uma dependência de runtime
npm install -D <pkg> # adiciona uma dependência de desenvolvimento
npm install -g <pkg> # instala uma ferramenta CLI globalmente
npm uninstall <pkg> # remove uma dependência
npm outdated # veja o que está desatualizado
npm update # atualiza dentro dos intervalos permitidos
npm install <pkg>@latest # salta para a versão mais recente
npm run <script> # executa um script do package.json
npx <pkg> # executa um pacote sem instalá-lo
É basicamente isso de npm. O resto — publicação, workspaces, pacotes com escopo — dá pra aprender quando aparecer a necessidade.
O que realmente existe dentro de node_modules
Um último modelo mental. A pasta node_modules é uma estrutura praticamente achatada que guarda todos os pacotes que seu projeto depende, mais tudo o que esses pacotes dependem, de forma transitiva. Instalar um pacote pode puxar uma centena junto — isso é normal. O npm tenta deduplicar sempre que possível, então dois pacotes que dependem da mesma versão do lodash compartilham uma única cópia.
O lockfile (package-lock.json) registra a versão exata resolvida de cada um desses pacotes. É justamente isso que garante builds reproduzíveis: dois desenvolvedores rodando npm install a partir do mesmo lockfile geram árvores idênticas byte a byte, mesmo meses depois.
Encare node_modules como saída gerada. Nunca edite arquivos lá dentro — suas alterações vão sumir na próxima vez que alguém rodar um install.
Próximo passo: package.json
O package.json é o arquivo que o npm fica lendo e reescrevendo nos bastidores. Dominar seus campos — scripts, main, type, ranges de versão, engines — é o que transforma o npm de uma caixa-preta em algo que você realmente controla. É isso que vem a seguir.
Perguntas frequentes
O que é o npm?
O npm é o gerenciador de pacotes padrão do Node.js. Ele já vem junto com o Node, dá acesso a um registro público gigantesco de pacotes JavaScript e oferece uma ferramenta de linha de comando para instalar, atualizar e publicar pacotes. Quando você roda npm install lodash, o npm baixa o lodash do registro para dentro do node_modules e registra a dependência no package.json.
Qual a diferença entre dependencies e devDependencies?
As dependencies são os pacotes que a sua aplicação precisa para rodar em produção — tipo express ou react. Já as devDependencies só são usadas durante o desenvolvimento ou build — são os test runners, bundlers e linters da vida. Para instalar como dev, use npm install --save-dev <pacote> (ou -D). Em produção, npm install --omit=dev ignora as devDependencies.
Preciso commitar o node_modules no git?
Não. O node_modules fácil passa dos centenas de megabytes e é totalmente reproduzível a partir do package.json + package-lock.json. Coloque ele no .gitignore e commite apenas o lockfile. Quem clonar o repositório só precisa rodar npm install e vai ter exatamente a mesma árvore de dependências.
O que significa instalar um pacote global ou local?
Uma instalação local (npm install <pacote>) coloca o pacote dentro do node_modules do seu projeto e registra no package.json. Já a global (npm install -g <pacote>) instala no sistema todo, normalmente para ferramentas de linha de comando que você quer disponíveis em qualquer lugar. Para dependências do projeto, prefira sempre a instalação local — assim cada projeto fica com suas próprias versões fixadas.