npm e o ecossistema de pacotes
Nesta aula, você aprenderá sobre o npm, o gerenciador de pacotes padrão do Node.js, e como ele organiza o ecossistema de bibliotecas JavaScript. Vamos explorar o arquivo package.json, a instalação de dependências, a criação de scripts e o versionamento semântico, com exemplos práticos e exercícios para fixar o conteúdo.
O npm (Node Package Manager) é o gerenciador de pacotes padrão do Node.js e uma das ferramentas mais importantes no ecossistema JavaScript. Ele permite que você instale, compartilhe e gerencie bibliotecas e ferramentas de código aberto, facilitando a reutilização de código e a colaboração em projetos. Com o npm, você pode rapidamente adicionar funcionalidades ao seu projeto sem precisar escrever tudo do zero.
Nesta aula, vamos mergulhar nos conceitos fundamentais do npm: o arquivo package.json, que é o coração de qualquer projeto Node.js; como instalar dependências de forma correta; como usar scripts para automatizar tarefas; e o versionamento semântico, que garante que as atualizações de pacotes sejam previsíveis. Ao final, você terá uma base sólida para trabalhar com qualquer projeto JavaScript moderno.
package.json
O arquivo package.json é o manifesto do seu projeto. Ele contém metadados como nome, versão, descrição, ponto de entrada, scripts, e, principalmente, a lista de dependências do projeto. Sem ele, o npm não sabe quais pacotes instalar ou como executar comandos personalizados. Todo projeto Node.js deve ter um package.json na raiz.
Você pode criar um package.json manualmente ou usando o comando npm init. O comando interativo faz perguntas e gera o arquivo com os campos básicos. Para um processo mais rápido, use npm init -y para aceitar os padrões.
Exemplo de um package.json típico:
{
"name": "meu-projeto",
"version": "1.0.0",
"description": "Um projeto de exemplo para aprender npm",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "jest"
},
"keywords": ["npm", "javascript", "exemplo"],
"author": "Seu Nome",
"license": "MIT",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"jest": "^29.5.0"
}
}
Os campos mais importantes são dependencies e devDependencies. O primeiro lista os pacotes necessários para o projeto rodar em produção; o segundo, apenas para desenvolvimento (como testes e ferramentas de build). O npm usa essas informações para instalar as versões corretas quando outra pessoa clona o projeto e roda npm install.
Instalando dependências
Para adicionar um pacote ao seu projeto, use o comando npm install <pacote>. Por padrão, isso adiciona o pacote à lista de dependencies e o instala na pasta node_modules. Se o pacote for usado apenas em desenvolvimento, use a flag --save-dev (ou -D) para adicioná-lo a devDependencies.
Exemplos:
# Instala uma dependência de produção
npm install express
# Instala uma dependência de desenvolvimento
npm install --save-dev jest
# Instala uma versão específica
npm install lodash@4.17.21
# Instala todas as dependências listadas no package.json
npm install
A pasta node_modules é criada automaticamente e contém todos os pacotes instalados. Ela não deve ser versionada no Git; em vez disso, usamos o arquivo package-lock.json (ou npm-shrinkwrap.json) para travar as versões exatas. Isso garante que todos os desenvolvedores tenham as mesmas versões, evitando surpresas.
Quando você clona um projeto, basta rodar npm install para instalar todas as dependências. O npm lê o package-lock.json e instala exatamente as versões ali registradas.
Scripts
Os scripts são comandos personalizados definidos no campo scripts do package.json. Eles permitem automatizar tarefas comuns, como iniciar o servidor, rodar testes, fazer build, etc. Você pode executá-los com npm run <nome-do-script> (ou npm <nome> para scripts especiais como start e test).
Exemplo de scripts:
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"build": "webpack --mode production",
"lint": "eslint ."
}
Para executar, use:
npm run start
npm run dev
npm test
npm run build
npm run lint
Os scripts podem ser combinados com o operador && (executa em sequência) ou & (em paralelo). Por exemplo: "build": "npm run lint && webpack --mode production". Além disso, você pode usar variáveis de ambiente e argumentos, mas isso é mais avançado.
Versionamento semântico
O versionamento semântico (SemVer) é um padrão para atribuir versões a pacotes, no formato MAJOR.MINOR.PATCH. Cada número tem um significado específico:
- MAJOR: incrementado quando há mudanças incompatíveis com versões anteriores (quebra de API).
- MINOR: incrementado quando são adicionadas funcionalidades compatíveis com versões anteriores.
- PATCH: incrementado quando são feitas correções de bugs compatíveis com versões anteriores.
No package.json, as versões das dependências podem ser especificadas com intervalos usando símbolos como ^, ~, >=, etc. O símbolo ^ permite atualizações que não mudam o número mais à esquerda não-zero. Por exemplo, ^4.18.2 aceita qualquer versão 4.x.x maior ou igual a 4.18.2, mas não 5.x.x. O ~ permite apenas atualizações de patch (ex.: ~4.18.2 aceita 4.18.x).
O arquivo package-lock.json registra as versões exatas instaladas, garantindo que todos os ambientes usem as mesmas versões. É importante entender essas regras para evitar que atualizações quebrem seu projeto.
Boas práticas
Algumas boas práticas ao trabalhar com npm:
- Mantenha o
package.jsone opackage-lock.jsonversionados no Git, mas ignorenode_modules. - Use
npm updatepara atualizar dependências dentro dos intervalos permitidos, enpm outdatedpara verificar versões desatualizadas. - Evite instalar pacotes globalmente, a menos que seja necessário (como ferramentas CLI). Prefira usar
npxpara executar pacotes sem instalá-los. - Documente os scripts no
README.mdpara que outros desenvolvedores saibam como rodar o projeto.
Referências
- npm install - Documentação oficial
- npm scripts - Documentação oficial
- package.json - Documentação oficial
- Semantic Versioning - Site oficial
- Node.js - Sobre o Node
- MDN - Linha de comando
Exercícios
-
Crie um
package.jsonmanualmente para um projeto chamadoexercicio-npm, com versão1.0.0, e adicione uma dependêncialodashna versão^4.17.21.✓ Resposta: O arquivo deve conter:{ "name": "exercicio-npm", "version": "1.0.0", "dependencies": { "lodash": "^4.17.21" } } -
Explique a diferença entre
dependenciesedevDependenciese dê um exemplo de cada tipo.✓ Resposta:dependenciessão pacotes necessários para o funcionamento em produção (ex.: express), enquantodevDependenciessão usados apenas em desenvolvimento (ex.: jest). -
Qual comando você usaria para instalar o pacote
axioscomo dependência de produção? E para instalar oeslintcomo dependência de desenvolvimento?✓ Resposta: Para produção:npm install axios. Para desenvolvimento:npm install --save-dev eslint. -
Escreva um script chamado
startque executenode server.jse um scriptdevque executenodemon server.js.✓ Resposta:"scripts": { "start": "node server.js", "dev": "nodemon server.js" } -
O que significa a versão
^2.3.1em uma dependência? Quais atualizações são permitidas?✓ Resposta: O^permite atualizações que não mudam o número mais à esquerda não-zero. Para^2.3.1, são permitidas versões2.x.xmaiores ou iguais a2.3.1, mas não3.x.x.