Pular para o conteúdo principal
Blog

Dependências Node.js: dependencies, devDependencies e peerDependencies

Atualizado em 18 de setembro de 2026

Node.js
npm
JavaScript

Como escolher a seção certa do package.json, publicar bibliotecas menores e lidar com incompatibilidades de major version.

Cada seção responde a uma pergunta diferente sobre uma dependência:

  • dependencies contém o que o código publicado precisa para rodar.
  • devDependencies contém as ferramentas usadas para desenvolver, testar e empacotar.
  • peerDependencies declara uma integração com um pacote que pertence ao projeto hospedeiro.
flowchart LR
    accTitle: Seções do package.json
    accDescr: Diagrama com as três seções do package.json. dependencies acompanha o código em produção, devDependencies atende o desenvolvimento e peerDependencies descreve uma biblioteca fornecida pelo projeto hospedeiro.
    A["<b>dependencies</b><br/><br/>O consumidor precisa<br/>deste pacote para<br/>executar a aplicação.<br/><br/><div class='diagram-chip diagram-chip--deps'><code>dependencies: {<br/>&nbsp;&nbsp;express: ^5.1.0<br/>}</code></div><br/><b>Runtime / produção</b>"]
    B["<b>devDependencies</b><br/><br/>A equipe precisa<br/>deste pacote para<br/>construir e testar.<br/><br/><div class='diagram-chip diagram-chip--dev'><code>devDependencies: {<br/>&nbsp;&nbsp;vitest: ^4.1.11<br/>}</code></div><br/><b>Build / teste / lint</b>"]
    C["<b>peerDependencies</b><br/><br/>Uma biblioteca espera<br/>que o hospedeiro<br/>forneça o pacote.<br/><br/><div class='diagram-chip diagram-chip--peer'><code>peerDependencies: {<br/>&nbsp;&nbsp;react: ^18.0.0<br/>}</code></div><br/><b>Plugin / host</b>"]
    A ~~~ B ~~~ C

Diagrama com as três seções do package.json. dependencies acompanha o código em produção, devDependencies atende o desenvolvimento e peerDependencies descreve uma biblioteca fornecida pelo projeto hospedeiro.

O que o npm instala

Considere um projeto que usa Astro. O servidor e o processo de build precisam do pacote astro, então ele aparece em dependencies neste projeto. O Vitest só é chamado pelos testes e o Oxlint só analisa o código durante o desenvolvimento. Ambos ficam em devDependencies.

{
  "dependencies": {
    "astro": "^7.2.4"
  },
  "devDependencies": {
    "vitest": "^4.1.11",
    "oxlint": "^1.80.0"
  }
}

Quando alguém instala a aplicação para executá-la, o ambiente precisa de astro. As ferramentas de teste e lint podem ficar de fora. No npm, npm install instala os dois grupos por padrão em um projeto local, e o comando de produção pode omitir o grupo de desenvolvimento com npm install --omit=dev.

Essa separação afeta o tamanho da instalação e o contrato do pacote. Colocar uma biblioteca de teste em dependencies informa aos consumidores que o código executado em produção precisa dela. Se o programa faz o import dessa biblioteca durante a execução, a declaração está correta; se ela só é usada nos testes e no desenvolvimento, o campo adequado é devDependencies.

dependencies pertence ao código que roda

Use dependencies quando o programa publicado importa um pacote em tempo de execução. Um servidor Express que chama express() precisa declarar express. Um pacote que valida dados com Zod numa função exportada precisa declarar zod.

{
  "name": "invoice-service",
  "dependencies": {
    "express": "^5.1.0",
    "zod": "^3.23.0"
  }
}

O consumidor não deveria precisar adivinhar essas dependências nem instalá-las manualmente. O npm lê o campo e monta a árvore necessária para executar o pacote.

O comando usual para adicionar uma dependência de produção é:

npm install express

O npm grava o nome e uma faixa de versão no package.json, além de registrar a versão resolvida e a integridade no package-lock.json. O lockfile fixa a árvore que o projeto instalou. A faixa no manifesto comunica quais versões futuras o pacote aceita.

devDependencies fica no lado da manutenção

Ferramentas de compilação, testes, lint e documentação costumam ficar em devDependencies. Elas ajudam a criar o pacote. O consumidor recebe o resultado do build e não precisa receber cada ferramenta usada para produzi-lo.

{
  "devDependencies": {
    "typescript": "^5.6.0",
    "vitest": "^4.1.11",
    "oxlint": "^1.80.0"
  },
  "scripts": {
    "build": "tsc",
    "test": "vitest run",
    "lint": "oxlint src"
  }
}

Adicione esses pacotes com npm install --save-dev pacote ou com a forma curta npm install -D pacote.

peerDependencies descreve o projeto hospedeiro

Uma peer dependency surge quando a biblioteca se integra a uma ferramenta que o aplicativo já escolheu. Plugins de React, adaptadores de bundlers e componentes para frameworks são exemplos comuns.

Imagine uma biblioteca form-kit que renderiza componentes React. Ela usa a API do React, porém não deve instalar uma cópia própria do React para cada aplicação. O app hospedeiro já possui uma versão, administra seu ciclo de atualização e fornece esse pacote.

{
  "name": "form-kit",
  "version": "2.4.0",
  "dependencies": {
    "zod": "^3.23.0"
  },
  "devDependencies": {
    "typescript": "^5.6.0",
    "vitest": "^2.1.0"
  },
  "peerDependencies": {
    "react": "^18.0.0"
  }
}

Essa declaração diz que form-kit é compatível com versões 18.x do React e espera encontrar React no projeto que o instala. A biblioteca ainda pode listar React em devDependencies para executar testes locais. O repositório consegue testar o código sem transferir a responsabilidade de instalar React para os consumidores.

Desde o npm 7, o npm tenta instalar peer dependencies automaticamente. Quando não consegue formar uma árvore compatível, acusa o conflito. O erro costuma surgir durante npm install, antes de qualquer código ser executado.

Quando uma major version quebra a faixa

SemVer usa o formato MAJOR.MINOR.PATCH. Uma mudança incompatível aumenta o número major. A faixa ^2.4.0 aceita versões a partir de 2.4.0 até antes de 3.0.0. Portanto, ela não aceita 3.0.0.

Esse limite aparece quando o pacote hospedeiro publica uma nova major. Suponha que o app tenha sido atualizado para host-ui@3.0.0, enquanto ui-addon@4.0.0 ainda declara:

{
  "peerDependencies": {
    "host-ui": "^2.4.0"
  }
}

Ao instalar o plugin, o npm encontra duas afirmações incompatíveis. O app exige host-ui@3.x. O plugin declara suporte apenas a host-ui@2.x. O resultado pode ser um ERESOLVE.

Terminal mostrando o erro ERESOLVE durante a instalação de ui-addon, com o conflito entre host-ui 3.0.0 e a peer dependency ^2.4.0.

O comando aparece na linha 1. A linha 2 identifica o código ERESOLVE, e a linha 3 resume que a árvore de dependências não pôde ser resolvida. A linha 4 mostra o projeto que está sendo resolvido; a linha 5 registra host-ui@3.0.0 e a linha 7 informa que essa versão veio do projeto raiz. Na linha 8, o npm anuncia a dependência que não conseguiu resolver; a linha 9 mostra que ui-addon@4.0.0 exige host-ui na faixa ^2.4.0. A linha 11 registra a versão conflitante encontrada.

O próximo passo depende do código do plugin. Se a API usada continua compatível, o mantenedor pode testar a versão 3 e ampliar a faixa:

{
  "peerDependencies": {
    "host-ui": "^2.4.0 || ^3.0.0"
  }
}

Se a versão 3 exige mudanças no código do plugin, o mantenedor precisa adaptar a implementação, testar as duas combinações e publicar uma versão que documente o novo suporte. A major do host-ui não obriga o plugin a aumentar sua própria major. O número do plugin depende das mudanças na sua própria API e do contrato que ele oferece aos consumidores.

Reduzir a faixa para "*" ou usar --legacy-peer-deps esconde o conflito. O comando pode terminar, porém a aplicação pode carregar uma API que o plugin não conhece. O erro do npm é informação sobre o contrato. O código e os testes precisam decidir se as versões são compatíveis.

Uma biblioteca pode listar o mesmo pacote em duas seções por motivos diferentes. React pode estar em peerDependencies para declarar o contrato com o consumidor e em devDependencies para os testes do próprio repositório; ele só deve entrar em dependencies quando o código publicado precisar dele durante a execução.

Referências