Qual é a diferença entre dependências, devDependencies e peerDependencies no arquivo npm package.json?

2029

Esta documentação responde muito mal à minha pergunta. Eu não entendi essas explicações. Alguém pode dizer em palavras mais simples? Talvez com exemplos, se é difícil escolher palavras simples?

EDIT também acrescentou peerDependencies, que está intimamente relacionado e pode causar confusão.

Vitalii Korsakov
fonte
48
Observe que também existem optionalDependenciesagora.
Aidan Feldman
118
@AidanFeldman "optionalDependencies" é o meu oxímoro do dia
Nick Bull
1
A documentação do npm diz: "dependencies": Pacotes requeridos pelo seu aplicativo em produção. "devDependencies": pacotes necessários apenas para desenvolvimento e teste local. veja o link: docs.npmjs.com/…
Deke

Respostas:

2366

Resumo das diferenças importantes de comportamento:

  • dependencies estão instalados em ambos:

    • npm install de um diretório que contém package.json
    • npm install $package em qualquer outro diretório
  • devDependencies estamos:

    • também instalado em npm installum diretório que contém package.json, a menos que você passe a --productionbandeira (faça um voto positivo com a resposta de Gayan Charith ).
    • não instalado em npm install "$package"nenhum outro diretório, a menos que você dê a --devopção.
    • não são instalados transitivamente.
  • peerDependencies:

    • antes do 3.0: sempre são instalados se estiverem ausentes e geram um erro se várias versões incompatíveis da dependência forem usadas por diferentes dependências.
    • espera-se que inicie no 3.0 (não testado): dê um aviso se estiver ausente npm installe você deverá resolver a dependência manualmente. Ao executar, se a dependência estiver ausente, você receberá um erro (mencionado por @nextgentech )
  • Transitividade (mencionada por Ben Hutchison ):

    • dependencies são instalados de forma transitória: se A requer B e B requer C, C é instalado; caso contrário, B não funcionaria e A.

    • devDependenciesnão está instalado transitivamente. Por exemplo, não precisamos testar B para testar A, para que as dependências de teste de B possam ser deixadas de fora.

Opções relacionadas não discutidas aqui:

devDependencies

dependenciessão necessários para executar, devDependenciesapenas para desenvolver, por exemplo: testes de unidade, transpilação CoffeeScript para JavaScript, minificação, ...

Se você estiver desenvolvendo um pacote, faça o download (por exemplo, via git clone), vá para a raiz que contém package.jsone execute:

npm install

Como você possui a fonte real, é claro que deseja desenvolvê-la; portanto, por padrão, ambas dependencies(desde que você deve, é claro, executar para desenvolver) e devDependencydependências também são instaladas.

Se, no entanto, você é apenas um usuário final que deseja instalar um pacote para usá-lo, faça isso em qualquer diretório:

npm install "$package"

Nesse caso, você normalmente não querem que as dependências de desenvolvimento, assim você só recebe o que é necessário para utilizar o pacote: dependencies.

Se você realmente deseja instalar pacotes de desenvolvimento nesse caso, pode definir a devopção de configuração para true, possivelmente na linha de comando, como:

npm install "$package" --dev

A opção é falsepor padrão, pois esse é um caso muito menos comum.

peerDependencies

(Testado antes da 3.0)

Fonte: https://nodejs.org/en/blog/npm/peer-dependencies/

Com dependências regulares, você pode ter várias versões da dependência: ela é simplesmente instalada dentro node_modulesda dependência.

Por exemplo, se dependency1e dependency2ambos dependem de dependency3versões diferentes, a árvore do projeto será semelhante a:

root/node_modules/
                 |
                 +- dependency1/node_modules/
                 |                          |
                 |                          +- dependency3 v1.0/
                 |
                 |
                 +- dependency2/node_modules/
                                            |
                                            +- dependency3 v2.0/

Plugins, no entanto, são pacotes que normalmente não exigem o outro pacote, chamado de host neste contexto. Em vez de:

  • plugins são requeridos pelo host
  • Os plugins oferecem uma interface padrão que o host espera encontrar
  • somente o host será chamado diretamente pelo usuário; portanto, deve haver uma única versão dele.

Por exemplo, se dependency1e dependency2ponto dependem dependency3, a árvore do projeto será semelhante a:

root/node_modules/
                 |
                 +- dependency1/
                 |
                 +- dependency2/
                 |
                 +- dependency3 v1.0/

Isso acontece mesmo que você nunca mencione dependency3no seu package.jsonarquivo.

Eu acho que essa é uma instância do padrão de design Inversion of Control .

Um exemplo prototípico de dependências entre pares é o Grunt, o host e seus plugins.

Por exemplo, em um plug-in Grunt como https://github.com/gruntjs/grunt-contrib-uglify , você verá que:

  • grunt é um peer-dependency
  • o único require('grunt')está abaixo tests/: não é realmente usado pelo programa.

Então, quando o usuário usar um plug-in, ele implicitamente exigirá o plug-in Gruntfileadicionando uma grunt.loadNpmTasks('grunt-contrib-uglify')linha, mas é gruntque o usuário chamará diretamente.

Isso não funcionaria se cada plug-in exigisse uma versão diferente do Grunt.

Manual

Acho que a documentação responde muito bem à pergunta, talvez você não esteja familiarizado o suficiente com os gerenciadores de nós / outros pacotes. Eu provavelmente só entendo porque sei um pouco sobre o empacotador Ruby.

A linha principal é:

Essas coisas serão instaladas durante a instalação do link npm ou npm a partir da raiz de um pacote e podem ser gerenciadas como qualquer outro parâmetro de configuração do npm. Veja npm-config (7) para mais informações sobre o tópico.

E então, em npm-config (7), localize dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.
Ciro Santilli adicionou uma nova foto
fonte
5
Ah Vejo que não entendi. Sua resposta é como npm install packageum comando que você usaria para instalar todos os pacotes que não são dependências de desenvolvimento, e não o que agora acho que você quis dizer, que era 'instalar o pacote chamado [pacote]', que era como eu pensava que funcionava. antes de ler isso. Se eu fosse você, editaria para dizer [nome do pacote], o que mostra claramente que o que você quer dizer é 'inserir nome do aqui'.
Tom W
184
Isso é ótimo! Eu nunca percebi, mas essa resposta me ensinou que a diferença entre dependências e devDependencies só é aplicável se você for publicar um pacote npm. Se você está apenas trabalhando em um aplicativo ou site, isso não deve importar muito. Obrigado!
precisa saber é o seguinte
3
Esta postagem deve ser atualizada para refletir o peerDependenciescomportamento alterado nas próximas npm @ 3. De blog.npmjs.org/post/110924823920/npm-weekly-5 : "Não baixaremos mais automaticamente a dependência de pares. Em vez disso, avisaremos se a dependência de pares ainda não estiver instalada. Isso exige que você resolver os conflitos de peerDependency manualmente, mas a longo prazo, isso deve tornar menos provável que você acabe em um ponto complicado com as dependências dos seus pacotes. "
nextgentech
8
Além disso, os devDependencies não são instalados transitivamente por pacotes dependentes. Exemplo: o pacote A depende do pacote B. O pacote B depende do pacote C e B também depende do pacote D. Se você executar o npm installpacote A, obterá B e C, mas não D.
Ben Hutchison
9
É importante observar que devDependenciesnão é instalado quando NODE_ENVestá definido como production.
Augusto Franzoia
491

Se você não deseja instalar o devDependencies, pode usar npm install --production

Gayan Charith
fonte
1
npm install --save é para dependência de software?
Vamsi Pavan Mahesh
19
O npm install instalará todas as dependências. O sinalizador --save é usado quando você deseja adicionar o módulo específico ao package.json também. ex: - npm install uglify --save instalará o uglify na sua pasta do projeto e adicionará o uglify ao projeto, arquivo package.json.
Gayan Charith
6
E como estamos falando de devDependencies, você pode usar --save-dev para salvar o novo módulo como devDependency. Exemplo: npm install uglify --save-dev
Mykaelos
9
A partir da NPM 5, a --saveopção não é mais necessária. Se você "npm instalar o meu pacote", ele adicionará o meu pacote como uma dependência no seu package.jsonarquivo.
Martin Carel
Instalação de apenas npm
sultan aslam
116

Como exemplo, o mocha normalmente seria uma devDependency, pois o teste não é necessário na produção, enquanto o express seria uma dependência.

Dan Kohn
fonte
4
Eu inclinar-se para colocar o teste como uma dependência desde que você pode querer executar auto-testes antes de lançar o servidor de produção
47
Em vez disso, eu recomendaria o uso de um serviço de integração contínua, como Hudson ou CircleCI, que executa seus testes e, em seguida, é implantado na produção, se eles passarem.
Dan Kohn
1
Ele ainda pode ser relevante para testar o servidor real porque o servidor CI pode ser diferente de alguma forma a partir do servidor prod, e essa diferença pode por exemplo, impedir que o aplicativo seja iniciado até ...
Nicole
2
@ Nicole, por que você tornaria seu servidor de temporariedade não idêntico em configuração ao seu prod?
21717 Lucas
1
Mais uma vez, adicionar dependências de teste como dependências regulares introduz um monte de bibliotecas extras, cada uma das quais pode falhar de alguma maneira. Eu me inclinaria (trocadilho!) Para servidores de produção leves, com o mínimo de código possível. Lembre-se, o melhor código não é código!
Stijn de Witt
69

dependências
Dependências que seu projeto precisa executar, como uma biblioteca que fornece funções que você chama do seu código.
Eles são instalados de forma transitória (se A depende de B depende de C, a instalação npm em A instalará B e C).
Exemplo: lodash: seu projeto chama algumas funções de lodash.

devDependencies
Dependências necessárias apenas durante o desenvolvimento ou a liberação, como compiladores que pegam seu código e o compilam em javascript, estruturas de teste ou geradores de documentação.
Eles não são instalados de forma transitória (se A depende de B dev - depende de C, a instalação do npm em A instalará apenas B).
Exemplo: grunt: seu projeto usa o grunt para se construir.

peerDependencies
Dependências nas quais seu projeto se conecta ou modifica no projeto pai, geralmente um plug-in para alguma outra biblioteca ou ferramenta. Pretende-se apenas ser uma verificação, certificando-se de que o projeto pai (projeto que dependerá do seu projeto) tenha uma dependência do projeto no qual você está conectado. Portanto, se você criar um plug-in C que adiciona funcionalidade à biblioteca B, alguém que cria um projeto A precisará ter uma dependência de B se tiver uma dependência de C.
Eles não estão instalados (a menos que npm <3), são apenas verificado.
Exemplo: grunt: seu projeto adiciona funcionalidade ao grunt e só pode ser usado em projetos que usam o grunt.

Esta documentação explica muito bem as dependências entre pares: https://nodejs.org/en/blog/npm/peer-dependencies/

Além disso, a documentação do npm foi aprimorada ao longo do tempo e agora possui explicações melhores dos diferentes tipos de dependências: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependencies

qwertzguy
fonte
63

Para salvar um pacote no package.json como dependências de dev:

npm install "$package" --save-dev

Quando você executa npm install, instala ambos devDependenciese dependencies. Para evitar a instalação, devDependenciesexecute:

npm install --production
Mohammed Safeer
fonte
3
você também pode usar: npm i -S
Maysara Alhindi
36

Existem alguns módulos e pacotes necessários apenas para o desenvolvimento, que não são necessários na produção. Como diz na documentação :

Se alguém estiver planejando baixar e usar seu módulo em seu programa, provavelmente não deseja ou precisa baixar e criar a estrutura de teste ou documentação externa que você usa. Nesse caso, é melhor listar esses itens adicionais em um hash devDependencies.

Amberlamps
fonte
E se você estiver executando apenas o arquivo bundle.js na produção? você realmente precisa dessas dependências?
RegarBoy 24/09
Se você estiver executando o bundle.js no servidor, estará executando o webpack do lado do servidor ou algo assim ... Verifique se esse é o caso, porque geralmente não é e realmente é necessário muito trabalho para que a execução seja executada corretamente (eu sei porque eu fiz isso). Eu suspeito que o seu bundle.js acabou de ser exibido nos navegadores e contém o código do lado do cliente.
Stijn de Witt
16

Uma explicação simples que me deixou mais claro é:

Quando você implanta seu aplicativo, os módulos nas dependências precisam ser instalados ou o aplicativo não funciona. Os módulos no devDependencies não precisam ser instalados no servidor de produção, pois você não está desenvolvendo nessa máquina. ligação

Jyoti Duhan
fonte
2
Então, se estivermos criando site e na versão prod todas as bibliotecas serão incluídas vendor.js, todos os nossos deps devem ser dev deps se o código compilado for confirmado no repositório? E deve ser comprometida, como otherwice é estranho que você tem que compilar módulo, não basta instalá-lo (e teste também é em algum lugar aqui como qualquer mudança na submódulos pode levar à regressão) ...
Qwertiy
Resposta impressionante, mas há uma pergunta? O Webpack possível cria um pacote corrompido? Meu palpite é que os pacotes devDependencies não funcionarão na versão do produto, webpack -pquero dizer. por favor responda minha pergunta.
AmerllicA
Se houver algum problema durante a criação da produção, seu processo de implantação deve ser projetado de forma a mostrar erro no momento da construção e não enviar código corrompido à produção (por exemplo, você pode experimentar o Jenkins). De qualquer forma, as desdependências não precisam ser instaladas no servidor de produção.
Jyoti Duhan
e as dependências entre pares?
dev27 28/01/19
13

Gostaria de acrescentar à resposta minha opinião sobre essas dependências explicações

  • dependencies são usados ​​para uso direto em sua base de código, coisas que geralmente acabam no código de produção ou em pedaços de código
  • devDependencies são usados ​​para o processo de criação, ferramentas que ajudam a gerenciar como o código final terminará, módulos de teste de terceiros, (por exemplo, material da webpack)
Sîrbu Nicolae-Cezar
fonte
E quanto aos recursos css?
Brian Zelip
8

Em resumo

  1. Dependências - npm install <package> --save-prodinstala pacotes exigidos pelo seu aplicativo no ambiente de produção.

  2. DevDependencies - npm install <package> --save-devinstala pacotes necessários apenas para desenvolvimento e teste local

  3. Apenas digitar npm installinstala todos os pacotes mencionados no package.json

então, se você estiver trabalhando no computador local, basta digitar npm installe continuar :)

cherankrish
fonte
6

peerDependenciesnão fazia muito sentido para mim até que li este trecho de um post no blog sobre o tópico mencionado por Ciro acima :

O que os [ plug-ins ] precisam é uma maneira de expressar essas “dependências” entre os plug-ins e seu pacote host. Alguma maneira de dizer: "Eu só trabalho quando conectado à versão 1.2.x do meu pacote de host; portanto, se você me instalar, verifique se ele está ao lado de um host compatível". Chamamos esse relacionamento de dependência entre pares.

O plugin espera uma versão específica do host ...

peerDependenciessão para plug-ins, bibliotecas que exigem uma biblioteca "host" para desempenhar suas funções, mas podem ter sido gravadas antes da versão mais recente do host.

Isto é, se eu escrever PluginX v1para HostLibraryX v3e ir embora, não há nenhuma garantia PluginX v1funcionará quando HostLibraryX v4(ou mesmo HostLibraryX v3.0.1) é liberado.

... mas o plugin não depende do host ...

Do ponto de vista do plug-in, ele apenas adiciona funções à biblioteca host. Eu realmente não "preciso" do host para adicionar uma dependência a um plug-in, e os plug-ins geralmente não dependem literalmente do host. Se você não possui o host, o plug-in inofensivamente não faz nada.

Isso significa que dependenciesnão é realmente o conceito certo para plugins.

Pior ainda, se meu host fosse tratado como uma dependência, acabaríamos nessa situação mencionada na mesma postagem do blog (editada um pouco para usar o host e o plugin compostos desta resposta):

Mas agora, [se tratarmos a versão contemporânea do HostLibraryX como uma dependência do PluginX], a execução npm installresulta no gráfico de dependência inesperado de

├── HostLibraryX@4.0.0
└─┬ PluginX@1.0.0
  └── HostLibraryX@3.0.0

Deixarei as falhas sutis que surgem do plug-in usando uma API [HostLibraryX] diferente da aplicação principal para sua imaginação.

... e o host obviamente não depende do plugin ...

... esse é o objetivo dos plugins. Agora, se o host fosse bom o suficiente para incluir informações de dependência para todos os seus plugins, isso resolveria o problema, mas também introduziria um enorme problema cultural novo : gerenciamento de plugins!

O ponto principal dos plug-ins é que eles podem emparelhar anonimamente. Em um mundo perfeito, ter o host gerenciando tudo seria limpo e arrumado, mas não precisaremos de bibliotecas que mantenham gatos.

Se não somos hierarquicamente dependentes, talvez sejamos colegas intradependentes ...

Em vez disso, temos o conceito de ser pares. Nem o host nem o plug-in ficam no balde de dependência do outro. Ambos vivem no mesmo nível do gráfico de dependência.


... mas este não é um relacionamento automatizável. <<< Moneyball !!!

Se eu sou PluginX v1e espero que um par de (ou seja, tenha uma dependência de par de ) HostLibraryX v3, eu direi. Se você atualizou automaticamente para a HostLibraryX v4versão mais recente (observe a versão 4 ) EPlugin v1instalou, você precisa saber, certo?

npm não pode gerenciar essa situação para mim -

"Ei, vejo que você está usando PluginX v1! Estou fazendo o downgrade automático HostLibraryXda v4 para a v3, ok?"

... ou ...

"Ei, eu vejo que você está usando PluginX v1. Isso espera HostLibraryX v3, que você deixou na poeira durante sua última atualização. Para ser seguro, eu estou desinstalando automaticamente Plugin v1!! 1!

Que tal não, npm ?!

Então npm não. Ele alerta você para a situação e permite que você descubra se HostLibraryX v4é um parceiro adequado Plugin v1.


Coda

Um bom peerDependencygerenciamento de plug-ins fará com que esse conceito funcione de forma mais intuitiva na prática. Da postagem do blog , mais uma vez ...

Um conselho: os requisitos de dependência entre pares, ao contrário dos requisitos comuns, devem ser branda. Você não deve bloquear suas dependências entre pares para versões específicas de patches. Seria realmente irritante se um plug-in do Chai dependesse dos pares do Chai 1.4.1, enquanto outro dependesse do Chai 1.5.0, simplesmente porque os autores eram preguiçosos e não passavam o tempo tentando descobrir a versão mínima real do Chai. compatível com.

ruffin
fonte
4

Dependências vs dependências de desenvolvimento

As dependências do desenvolvedor são módulos necessários apenas durante o desenvolvimento, enquanto as dependências são necessárias no tempo de execução. Se você estiver implantando seu aplicativo, é necessário instalar dependências, caso contrário, seu aplicativo simplesmente não funcionará. Bibliotecas que você chama de seu código que permite a execução do programa podem ser consideradas dependências.

Por exemplo, reagir, reagir - dom

Os módulos de dependência de desenvolvimento não precisam ser instalados no servidor de produção, pois você não desenvolverá nessa máquina .compiladores que escondem seu código em javascript, estruturas de teste e geradores de documentos podem ser considerados dependências de desenvolvimento, pois são necessários apenas durante o desenvolvimento.

Por exemplo, ESLint, Babel, webpack

@PARA SUA INFORMAÇÃO,

mod-a
  dev-dependents:
    - mod-b
  dependents:
    - mod-c

mod-d
  dev-dependents:
    - mod-e
  dependents:
    - mod-a

----

npm install mod-d

installed modules:
  - mod-d
  - mod-a
  - mod-c

----

checkout the mod-d code repository

npm install

installed modules:
  - mod-a
  - mod-c
  - mod-e

Se você estiver publicando no npm, é importante usar o sinalizador correto para os módulos corretos. Se for necessário que o seu módulo npm funcione, use o sinalizador "--save" para salvar o módulo como uma dependência. Se é algo que seu módulo não precisa funcionar, mas é necessário para testar, use o sinalizador "--save-dev".

# For dependent modules
npm install dependent-module --save

# For dev-dependent modules
npm install development-module --save-dev
Selva Ganapathi
fonte
1

Ao tentar distribuir um pacote npm, você deve evitar o uso dependencies. Em vez disso, você deve considerar adicioná-lo peerDependenciesou removê-lo dependencies.

Melchia
fonte
1

Eu encontrei uma explicação simples.

Resposta curta:

dependências "... são aquelas que o seu projeto realmente precisa para poder trabalhar na produção."

devDependencies "... são aqueles que você precisa durante o desenvolvimento."

peerDependencies "se você deseja criar e publicar sua própria biblioteca para que possa ser usada como uma dependência"

Mais detalhes nesta publicação: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

usuário precisa de ajuda
fonte