Pular para o conteúdo

O que é NPM (Node Package Manager) e por que todo dev precisa conhecer?

Se você está começando no mundo do JavaScript ou já ouviu falar de Node.js, provavelmente já esbarrou no famoso NPM — mas afinal, o que é isso e por que todo desenvolvedor fala tanto sobre ele?
O NPM (Node Package Manager) é o gerenciador de pacotes padrão do Node.js e um dos pilares do ecossistema JavaScript moderno. Em termos simples, ele permite que você instale, compartilhe e gerencie bibliotecas e dependências de forma rápida e organizada, sem precisar reinventar a roda a cada novo projeto.

Imagine criar uma aplicação do zero sem precisar escrever tudo manualmente: autenticação, validação de dados, rotas, testes, formatação de código… É exatamente aí que o NPM entra em cena. Com poucos comandos no terminal, você pode adicionar milhares de pacotes prontos, criados e mantidos pela comunidade, economizando tempo e aumentando a qualidade do seu código.

Além disso, o NPM ajuda a manter seus projetos organizados por meio do arquivo package.json, onde ficam registradas informações importantes como dependências, scripts, versão do projeto e muito mais. Isso torna o trabalho em equipe muito mais simples e previsível — algo essencial no mercado profissional.

Neste artigo, vamos entender o que é o NPM, como ele funciona, por que ele é tão importante e como você pode começar a usá-lo hoje mesmo, mesmo que esteja dando seus primeiros passos na programação. Sem complicação, sem termos confusos — do jeito que dev gosta.

O que é o NPM na prática? Entendendo de forma simples

Agora que você já sabe o que é o NPM, vamos trazer isso para a prática. Na vida real, o NPM funciona como uma grande biblioteca online, onde desenvolvedores do mundo todo publicam pacotes prontos para resolver problemas comuns do dia a dia.

Esses pacotes podem ser desde algo simples, como formatar datas, até coisas mais complexas, como frameworks completos (Express, NestJS, React, Next.js, entre muitos outros). Em vez de você escrever tudo do zero, o NPM permite que você reaproveite código confiável, testado e usado por milhares (ou milhões) de pessoas.

Quando você instala o Node.js no seu computador, o NPM já vem instalado automaticamente. Isso significa que você não precisa configurar nada extra para começar. Basta abrir o terminal e digitar:

npm -v

Se aparecer uma versão, pronto: o NPM já está funcionando.

Na prática, sempre que você cria um projeto JavaScript com Node.js, você usa o NPM para:

  • Instalar dependências (bibliotecas externas)
  • Atualizar pacotes
  • Remover pacotes que não são mais necessários
  • Executar scripts automatizados (como rodar o projeto ou executar testes)

Tudo isso gira em torno de um arquivo muito importante chamado package.json, que funciona como o “RG” do seu projeto. É nele que o NPM registra quais pacotes o projeto usa, quais versões, quais scripts existem e até informações como nome, versão e descrição do projeto.

Um ponto muito legal é que o NPM também cria automaticamente a pasta node_modules, onde ficam todas as dependências instaladas. Você não precisa mexer nela diretamente — o NPM cuida disso pra você.

Resumindo: NPM é o que torna o desenvolvimento com Node.js rápido, organizado e profissional. Sem ele, trabalhar com JavaScript moderno seria muito mais difícil e bagunçado.

Criando um projeto com NPM do zero (passo a passo)

Agora vamos para a parte que todo iniciante gosta: mão na massa
Criar um projeto com NPM é mais simples do que parece, e em poucos minutos você já terá tudo pronto para começar a programar.

Passo 1: Criando a pasta do projeto

Primeiro, crie uma pasta para o seu projeto e entre nela pelo terminal:

mkdir meu-primeiro-projeto
cd meu-primeiro-projeto

Aqui você pode escolher qualquer nome. Em projetos reais, é comum usar nomes curtos e descritivos.

Passo 2: Inicializando o NPM

Dentro da pasta do projeto, execute o comando:

npm init

Esse comando inicia um assistente que vai fazer algumas perguntas, como:

  • Nome do projeto
  • Versão
  • Descrição
  • Autor
  • Arquivo principal

Se você quiser ir mais rápido, pode usar:

npm init -y

Esse comando cria tudo automaticamente com valores padrão. Para iniciantes, ele é perfeito.

Passo 3: Entendendo o package.json

Após rodar o npm init, o NPM cria o arquivo package.json. Esse arquivo é o coração do seu projeto. É nele que ficam:

  • Nome e versão do projeto
  • Dependências instaladas
  • Scripts personalizados
  • Informações importantes para outros devs

Exemplo simples de package.json:

{
  "name": "meu-primeiro-projeto",
  "version": "1.0.0",
  "scripts": {
    "start": "node index.js"
  }
}

Tudo o que você fizer com o NPM vai refletir aqui.

Passo 4: Por que isso é tão importante?

Esse processo garante que qualquer pessoa que baixar seu projeto consiga rodá-lo facilmente, apenas usando:

npm install

Sem dor de cabeça, sem “funciona só na minha máquina”.

Instalando pacotes com NPM: dependencies e devDependencies

Agora que você já tem um projeto criado, chegou a hora de entender o principal motivo de usar o NPM: instalar pacotes. É aqui que a mágica acontece.

Instalando um pacote

Para instalar um pacote no seu projeto, basta rodar:

npm install nome-do-pacote

Por exemplo, para instalar o Express, um dos frameworks mais usados com Node.js:

npm install express

Quando você faz isso, três coisas acontecem automaticamente:

  1. O pacote é baixado do repositório oficial do NPM
  2. Ele é colocado dentro da pasta node_modules
  3. Ele é registrado no arquivo package.json

O que são dependencies?

Por padrão, todo pacote instalado vai para a seção dependencies do package.json.
Essas são as bibliotecas essenciais para o funcionamento da aplicação em produção.

Exemplo:

"dependencies": {
  "express": "^4.19.2"
}

Se sua aplicação usa Express para funcionar, ele precisa estar aqui.

O que são devDependencies?

Já as devDependencies são pacotes usados apenas durante o desenvolvimento, como:

  • Ferramentas de teste (Jest, Mocha)
  • Formatadores de código (Prettier)
  • Linters (ESLint)
  • Ferramentas de build

Para instalar um pacote como dependência de desenvolvimento, use:

npm install eslint --save-dev

Ou a forma mais curta:

npm i eslint -D

No package.json, ele aparecerá assim:

"devDependencies": {
  "eslint": "^8.0.0"
}

Por que separar isso é importante?

Essa separação ajuda a:

  • Deixar o projeto mais leve em produção
  • Evitar instalar coisas desnecessárias no servidor
  • Manter o projeto mais organizado e profissional

node_modules: o que é essa pasta gigante e por que você não deve mexer nela

Se você já criou um projeto com NPM, com certeza notou que surgiu uma pasta chamada node_modules. Normalmente ela aparece do nada, ocupa muito espaço e assusta quem está começando. Mas calma, isso é totalmente normal.

A pasta node_modules é onde o NPM guarda todos os pacotes instalados no seu projeto, além das dependências desses pacotes. Ou seja, quando você instala um único pacote, ele pode trazer vários outros junto. É por isso que essa pasta cresce tão rápido.

Por que a node_modules é tão grande?

Isso acontece porque o ecossistema JavaScript trabalha com muitas dependências pequenas e reutilizáveis. Cada pacote pode depender de outros pacotes, que dependem de outros… formando uma árvore completa de dependências.

A boa notícia é: você não precisa entender tudo o que tem lá dentro.
E melhor ainda: você quase nunca deve mexer nessa pasta manualmente.

Por que não versionar a node_modules no Git?

Uma das regras mais importantes do Node.js é:

Nunca suba a pasta node_modules para o Git.

Motivos:

  • Ela pode ser recriada facilmente com npm install
  • Deixa o repositório muito pesado
  • Pode causar conflitos entre sistemas diferentes

Por isso, sempre adicione node_modules no seu arquivo .gitignore:

node_modules/

Então como outra pessoa roda o projeto?

Simples! Basta clonar o repositório e rodar:

npm install

O NPM lê o package.json (e o package-lock.json) e recria tudo exatamente como você precisa.

Resumo rápido

  • node_modules guarda todas as dependências
  • Ela é grande, e isso é normal
  • Não mexa nela manualmente
  • Nunca versione no Git

package-lock.json: por que esse arquivo é tão importante?

Além do package.json, quando você usa o NPM surge outro arquivo que muita gente ignora no começo: o package-lock.json. E já vou adiantar: ele é extremamente importante.

O que é o package-lock.json?

O package-lock.json é um arquivo gerado automaticamente pelo NPM que registra a versão exata de cada pacote instalado, incluindo as dependências internas de cada biblioteca.

Enquanto o package.json diz algo como:

"express": "^4.19.2"

O package-lock.json diz exatamente:

  • Qual versão foi instalada
  • Quais subdependências foram usadas
  • A estrutura completa da árvore de dependências

Ou seja, ele garante que todas as pessoas que rodarem o projeto usem exatamente as mesmas versões.

Por que isso evita problemas?

Sem o package-lock.json, cada pessoa poderia instalar versões ligeiramente diferentes dos pacotes, mesmo usando o mesmo package.json. Isso leva ao famoso problema:

“Na minha máquina funciona”

Com o package-lock.json, o NPM instala tudo de forma idêntica em qualquer ambiente:

  • No seu computador
  • No computador de outro dev
  • No servidor de produção
  • Em pipelines de CI/CD

Devo versionar o package-lock.json?

Sim!
Diferente da node_modules, o package-lock.json deve ser versionado no Git. Ele faz parte do controle de qualidade do projeto.

Quando ele é atualizado?

O NPM atualiza o package-lock.json quando você:

  • Instala um novo pacote
  • Remove um pacote
  • Atualiza dependências

Você não deve editar esse arquivo manualmente. Assim como a node_modules, o NPM cuida disso pra você.

Scripts do NPM: automatizando tarefas do dia a dia

Uma das partes mais poderosas (e menos exploradas por iniciantes) do NPM são os scripts. Eles permitem que você crie comandos personalizados para automatizar tarefas comuns do seu projeto, economizando tempo e evitando erros.

O que são scripts do NPM?

Scripts são comandos definidos dentro do package.json, na seção "scripts". Eles permitem que você execute tarefas como:

  • Iniciar o projeto
  • Rodar o servidor
  • Executar testes
  • Rodar linters e formatadores
  • Fazer build da aplicação

Exemplo simples:

"scripts": {
  "start": "node index.js"
}

Com isso, você pode rodar no terminal:

npm run start

Ou, no caso do script start, apenas:

npm start

Scripts mais comuns

Alguns scripts são tão comuns que praticamente viraram padrão no mercado:

"scripts": {
  "dev": "node index.js",
  "start": "node index.js",
  "test": "jest"
}
  • npm run dev → usado para desenvolvimento
  • npm start → usado para produção
  • npm test → roda os testes

Frameworks como React, Next.js e NestJS já vêm com scripts prontos, justamente para facilitar a vida do dev.

Por que scripts são tão importantes?

Eles ajudam a:

  • Padronizar comandos no time
  • Evitar erros de digitação
  • Facilitar a entrada de novos devs no projeto
  • Automatizar tarefas repetitivas

Em vez de explicar “roda esse comando gigante aqui”, você diz apenas:

“Roda npm run dev

Muito mais profissional

Dica importante

Scripts do NPM também funcionam com ferramentas instaladas em devDependencies, sem precisar instalar nada globalmente. Isso deixa o ambiente mais limpo e controlado.

Instalação local vs global no NPM: qual a diferença?

Quando você começa a usar o NPM, logo aparece uma dúvida clássica: instalar pacotes localmente ou globalmente?
Entender essa diferença é essencial para evitar problemas no seu ambiente de desenvolvimento.

Instalação local (a mais comum)

A instalação local é quando o pacote é instalado dentro do projeto, na pasta node_modules, e registrado no package.json.

Exemplo:

npm install express

Esse é o padrão e o mais recomendado na maioria dos casos.
Pacotes instalados localmente:

  • Funcionam apenas naquele projeto
  • Garantem que todos usem a mesma versão
  • Evitam conflitos entre projetos diferentes

Frameworks, bibliotecas e ferramentas de build devem quase sempre ser locais.

Instalação global

A instalação global acontece quando você usa a flag -g:

npm install -g nodemon

Nesse caso, o pacote fica disponível no sistema inteiro, podendo ser usado em qualquer pasta.

Pacotes globais são ideais para:

  • Ferramentas de linha de comando (CLI)
  • Geradores de projetos
  • Utilitários usados fora de um projeto específico

Exemplos comuns:

  • nodemon
  • npm
  • npx
  • typescript (em alguns casos)

Quando evitar instalação global?

Evite instalar bibliotecas de projeto globalmente. Isso pode causar:

  • Diferença de versões entre devs
  • Erros em ambientes de CI/CD
  • O famoso “funciona só na minha máquina”

Boa prática moderna

Hoje em dia, a recomendação é:

🔹 Instale ferramentas como devDependencies e execute via scripts do NPM

Assim, todo mundo usa a mesma versão, sem depender do ambiente local.

npx: executando pacotes sem instalar nada

Se você já ficou em dúvida se deveria instalar algo globalmente ou localmente, o npx vem justamente para resolver esse problema. Ele é uma ferramenta que já vem junto com o NPM e facilita muito a vida do desenvolvedor.

O que é o npx?

O npx permite que você execute pacotes diretamente, sem precisar instalá-los globalmente no seu computador. Ele baixa o pacote temporariamente, executa o comando e depois descarta — simples assim.

Exemplo clássico:

npx create-react-app meu-app

Nesse caso, você não precisa instalar o create-react-app globalmente. O npx cuida de tudo.

Por que o npx é tão útil?

Ele ajuda a:

  • Evitar poluir o ambiente global
  • Garantir que você use sempre a versão correta da ferramenta
  • Executar comandos rapidamente
  • Facilitar a criação de projetos

Hoje em dia, muitos frameworks modernos usam npx como padrão, como:

  • React
  • Next.js
  • NestJS
  • Vite

Exemplo com Vite:

npx create-vite@latest

Você já começa um projeto novo em segundos.

npx vs npm run

  • npx → executa pacotes diretamente
  • npm run → executa scripts definidos no package.json

Eles não competem entre si, pelo contrário: se complementam.

Dica importante

Se o pacote já estiver instalado localmente no projeto, o npx vai usar essa versão local automaticamente. Isso garante mais segurança e consistência.

Atualizando e removendo pacotes com NPM (manutenção do projeto)

Com o tempo, todo projeto cresce, evolui e precisa de manutenção. Saber atualizar e remover pacotes com NPM é essencial para manter sua aplicação segura, organizada e sem dependências desnecessárias.

Atualizando pacotes

Para atualizar pacotes, você tem algumas opções.

Atualizar um pacote específico:

npm update express

Esse comando atualiza o pacote respeitando as regras de versão definidas no package.json.

Para ver quais pacotes podem ser atualizados:

npm outdated

Esse comando mostra:

  • A versão atual
  • A versão desejada
  • A versão mais recente disponível

Atualizando para versões mais novas

Se você quiser atualizar para a versão mais recente (inclusive major), pode usar:

npm install express@latest

Isso também atualiza o package.json e o package-lock.json.

Removendo pacotes

Quando um pacote não é mais necessário, você pode removê-lo facilmente:

npm uninstall express

O NPM:

  • Remove o pacote da node_modules
  • Atualiza o package.json
  • Atualiza o package-lock.json

Se for uma devDependency:

npm uninstall eslint --save-dev

Ou simplesmente:

npm uninstall eslint

Por que manter dependências organizadas?

Manter os pacotes em dia ajuda a:

  • Corrigir falhas de segurança
  • Melhorar performance
  • Evitar conflitos de versões
  • Facilitar upgrades futuros

Mas atenção: evite atualizar tudo sem testar. Em projetos reais, sempre valide as mudanças antes de subir para produção.

Versionamento Semântico (SemVer): Como entender as versões dos pacotes

O versionamento semântico ou SemVer é um sistema que organiza as versões dos pacotes de forma que seja fácil entender o que mudou entre uma versão e outra, apenas olhando os números. Isso é superimportante, especialmente quando você está lidando com dependências no NPM.

O que é SemVer?

O SemVer segue o formato de três números: MAJOR.MINOR.PATCH.

Exemplo de versão:

1.2.3

Cada número tem um significado específico:

  • MAJOR: Mudanças incompatíveis, que podem quebrar seu código. Quando há mudanças que não são retrocompatíveis, o número da versão major é alterado.
  • MINOR: Novas funcionalidades compatíveis com versões anteriores. Ou seja, novas features sem quebrar o código já existente.
  • PATCH: Correções de bugs e melhorias pequenas, sem alteração na funcionalidade. Usado para ajustes ou otimizações.

Como o NPM usa o SemVer?

No arquivo package.json, quando você define a versão de um pacote, pode usar alguns símbolos especiais para indicar o tipo de atualização que você quer permitir.

Exemplos:

  • "express": "^1.2.3" → Significa qualquer versão maior ou igual a 1.2.3, mas menor que 2.0.0. Ou seja, permite atualizações minores e patches, mas não majors.
  • "express": "~1.2.3" → Significa qualquer versão maior ou igual a 1.2.3, mas menor que 1.3.0. Aqui, ele permite apenas atualizações patch (menor que a próxima versão minor).
  • "express": "1.2.3" → Significa somente essa versão exata. Não permite atualizações, nem patch, nem minor, nem major.

Por que o SemVer é importante?

Entender a lógica de versionamento semântico ajuda a:

  • Evitar quebras de código ao atualizar dependências.
  • Manter o controle sobre novas funcionalidades ou correções de bugs.
  • Facilitar a atualização segura de pacotes, sem surpresas.

Ao instalar pacotes, o NPM usa essas regras para garantir que as atualizações sejam feitas de forma controlada e previsível.

Dica importante

Se você usa um pacote de terceiros e ele lançar uma nova versão major (ex: de 1.x.x para 2.x.x), é sempre bom testar o código antes de atualizar, pois pode haver mudanças incompatíveis com seu projeto.

Boas práticas ao usar o NPM em projetos reais

Agora que você já entende como o NPM funciona, versões, scripts e dependências, é hora de falar de boas práticas. Essas são dicas que fazem muita diferença quando você sai de projetos de estudo e começa a trabalhar em projetos reais, sozinho ou em equipe.

1. Sempre versione o package.json e o package-lock.json

Esses dois arquivos são essenciais. Eles garantem que qualquer pessoa consiga rodar o projeto da mesma forma que você.
Lembre-se:

  • package.json → sempre versionar
  • package-lock.json → sempre versionar
  • node_modules → nunca versionar

2. Evite dependências desnecessárias

Antes de instalar um pacote, pergunte:

“Eu realmente preciso disso?”

Muitos projetos ficam pesados e difíceis de manter por excesso de dependências. Às vezes, algumas linhas de código resolvem o problema sem adicionar mais uma biblioteca.

3. Prefira dependências locais em vez de globais

Sempre que possível, instale ferramentas como devDependencies e use scripts do NPM para executá-las. Isso evita conflitos de versão e deixa o projeto mais previsível.

4. Use nomes claros para scripts

Scripts como start, dev, build e test ajudam qualquer dev a entender rapidamente como o projeto funciona. Evite nomes confusos ou genéricos demais.

5. Atualize dependências com cuidado

Atualizar pacotes é importante, mas faça isso com atenção:

  • Veja o changelog
  • Teste localmente
  • Evite atualizar tudo de uma vez em projetos grandes

6. Fique atento à segurança

O NPM oferece uma ferramenta nativa para verificar vulnerabilidades:

npm audit

E para tentar corrigir automaticamente:

npm audit fix

Isso ajuda a manter seu projeto mais seguro, especialmente em produção.

Por que dominar o NPM é essencial para a carreira do desenvolvedor JavaScript

Se você quer trabalhar profissionalmente com JavaScript, seja no backend com Node.js ou no frontend com React, Vue ou Next.js, dominar o NPM não é opcional — é obrigatório. Ele faz parte do dia a dia de praticamente todo time de desenvolvimento moderno.

Na prática, empresas não procuram apenas alguém que “sabe programar”. Elas procuram devs que sabem:

  • Criar projetos organizados
  • Gerenciar dependências corretamente
  • Evitar problemas de versão
  • Automatizar tarefas
  • Trabalhar bem em equipe

E tudo isso passa diretamente pelo NPM.

NPM no mercado de trabalho

Em entrevistas técnicas, é muito comum aparecerem perguntas como:

  • Qual a diferença entre dependencies e devDependencies?
  • Para que serve o package-lock.json?
  • Quando usar npm install ou npm ci?
  • Como evitar problemas de versão em um time?

Quem domina o NPM responde isso com tranquilidade 😎.

NPM vai além de instalar pacotes

O NPM não é só um instalador de bibliotecas. Ele é uma ferramenta que ajuda você a:

  • Padronizar projetos
  • Criar ambientes previsíveis
  • Automatizar processos
  • Aumentar a qualidade do código

É exatamente por isso que frameworks modernos dependem tanto dele.

Conclusão final

O NPM (Node Package Manager) é uma das ferramentas mais importantes do ecossistema JavaScript. Desde o primeiro “Hello World” até aplicações grandes em produção, ele está sempre presente.

Se você está começando agora, aprender NPM desde cedo vai acelerar muito sua evolução como desenvolvedor. E se você já é mais experiente, dominar boas práticas com NPM te coloca um passo à frente no mercado.

💬 E você?
Já teve algum problema com dependências no NPM ou tem alguma dúvida sobre o assunto?
Deixa seu comentário aqui — sua pergunta pode virar o próximo artigo!