Qual è la differenza tra dipendenze, devDependencies e peerDependencies nel file npm package.json?


2030

Questa documentazione risponde alla mia domanda molto male. Non ho capito quelle spiegazioni. Qualcuno può dire in parole più semplici? Forse con esempi se è difficile scegliere parole semplici?

È stato inoltre aggiunto EDITpeerDependencies , che è strettamente correlato e potrebbe causare confusione.


48
Nota che ci sono anche optionalDependenciesora.
Aidan Feldman,

118
@AidanFeldman "optionalDependencies" è il mio ossimoro del giorno
Nick Bull,

1
La documentazione di npm dice: "dipendenze": pacchetti richiesti dall'applicazione in produzione. "devDependencies": pacchetti necessari solo per sviluppo e test locali. vedi link: docs.npmjs.com/…
Deke,

Risposte:


2367

Riepilogo di importanti differenze comportamentali:

  • dependencies sono installati su entrambi:

    • npm install da una directory che contiene package.json
    • npm install $package su qualsiasi altra directory
  • devDependencies siamo:

    • installato anche npm installsu una directory che contiene package.json, a meno che non passi la --productionbandiera (vai a votare la risposta di Gayan Charith ).
    • non installato su npm install "$package"qualsiasi altra directory, a meno che tu non gli dia l' --devopzione.
    • non sono installati in modo transitorio.
  • peerDependencies:

    • prima della 3.0: vengono sempre installati se mancanti e generano un errore se più dipendenze della dipendenza sarebbero utilizzate da versioni diverse incompatibili.
    • dovrebbe iniziare su 3.0 (non testato): dare un avviso se manca su npm installe si deve risolvere manualmente la dipendenza. Durante l'esecuzione, se manca la dipendenza, viene visualizzato un errore (menzionato da @nextgentech )
  • Transitività (menzionata da Ben Hutchison ):

    • dependencies sono installati in modo transitorio: se A richiede B e B richiede C, allora C viene installato, altrimenti B non potrebbe funzionare e nemmeno A.

    • devDependenciesnon è installato in modo transitivo. Ad esempio, non abbiamo bisogno di testare B per testare A, quindi le dipendenze di test B possono essere tralasciate.

Opzioni correlate non discusse qui:

devDependencies

dependenciessono necessari per l'esecuzione, devDependenciessolo per lo sviluppo, ad esempio: unit test, conversione da CoffeeScript a JavaScript, minificazione, ...

Se hai intenzione di sviluppare un pacchetto, lo scarichi (ad es. Via git clone), vai alla sua radice che contiene package.jsoned esegui:

npm install

Dal momento che hai la fonte reale, è chiaro che vuoi svilupparla, quindi per impostazione predefinita, sono installati sia dependencies(poiché, ovviamente, devi correre per sviluppare) sia le devDependencydipendenze.

Se tuttavia, sei solo un utente finale che desidera semplicemente installare un pacchetto per usarlo, lo farai da qualsiasi directory:

npm install "$package"

In questo caso, normalmente non si desidera che le dipendenze di sviluppo, quindi basta avere ciò che è necessario per utilizzare il pacchetto: dependencies.

Se vuoi davvero installare i pacchetti di sviluppo in quel caso, puoi impostare l' devopzione di configurazione su true, possibilmente dalla riga di comando come:

npm install "$package" --dev

L'opzione è falsedi default poiché questo è un caso molto meno comune.

peerDependencies

(Testato prima di 3.0)

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

Con le dipendenze regolari, è possibile avere più versioni della dipendenza: è semplicemente installata all'interno node_modulesdella dipendenza.

Ad esempio, se dependency1e dependency2entrambi dipendono dependency3in diverse versioni ad albero del progetto sarà simile:

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

I plug-in, tuttavia, sono pacchetti che normalmente non richiedono l'altro pacchetto, chiamato host in questo contesto. Anziché:

  • i plugin sono richiesti dall'host
  • i plugin offrono un'interfaccia standard che l'host si aspetta di trovare
  • solo l'host verrà chiamato direttamente dall'utente, quindi deve esserci una sola versione di esso.

Ad esempio, se dependency1e dependency2peer dipendono dependency3, l'albero del progetto sarà simile a:

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

Questo succede anche se non hai mai menzionato dependency3nel tuo package.jsonfile.

Penso che questa sia un'istanza del modello di progettazione di Inversion of Control .

Un esempio prototipico di dipendenze tra pari è Grunt, l'host e i suoi plugin.

Ad esempio, su un plug-in Grunt come https://github.com/gruntjs/grunt-contrib-uglify , vedrai che:

  • grunt è un peer-dependency
  • l'unico require('grunt')è sotto tests/: non è effettivamente utilizzato dal programma.

Quindi, quando l'utente utilizzerà un plugin, richiederà implicitamente il plugin Gruntfileaggiungendo una grunt.loadNpmTasks('grunt-contrib-uglify')linea, ma è gruntche l'utente chiamerà direttamente.

Questo non funzionerebbe quindi se ogni plugin richiedesse una versione di Grunt diversa.

Manuale

Penso che la documentazione risponda abbastanza bene alla domanda, forse non hai abbastanza familiarità con i gestori di nodi / altri pacchetti. Probabilmente lo capisco solo perché conosco un po 'il bundler di Ruby.

La linea chiave è:

Queste cose verranno installate quando si esegue npm link o npm install dalla radice di un pacchetto e possono essere gestite come qualsiasi altro parametro di configurazione npm. Vedi npm-config (7) per ulteriori informazioni sull'argomento.

E poi sotto npm-config (7) trova dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.

5
Ah. Vedo che ho frainteso. La tua risposta si legge come se npm install packagefosse un comando che avresti usato per installare tutti i pacchetti che non sono dipendenze degli sviluppatori, piuttosto che quello che penso ora intendevi, che era "installa il pacchetto chiamato [pacchetto]", che era come pensavo funzionasse prima di leggere questo. Se fossi in te, modificherei per dire [nome-pacchetto] che mostra chiaramente che ciò che intendi è "inserisci-nome-qui".
Tom W,

184
Questo è fantastico! Non me ne sono mai reso conto, ma questa risposta mi ha insegnato che la differenza tra dipendenze e devDependencies è applicabile solo se stai per pubblicare un pacchetto npm. Se stai solo lavorando su un'applicazione o un sito, non dovrebbe importare troppo. Grazie!
jedd.ahyoung,

3
Questo post deve essere aggiornato per riflettere il peerDependenciescomportamento modificato nel prossimo npm @ 3. Da blog.npmjs.org/post/110924823920/npm-weekly-5 : "Non avremo più il download automatico della dipendenza peer. Invece, ti avvertiremo se la dipendenza peer non è già installata. Ciò richiede che tu per risolvere i conflitti peerDependency manualmente, ma a lungo termine ciò dovrebbe rendere meno probabile che finirai in una posizione difficile con le dipendenze dei tuoi pacchetti ".
nextgentech,

8
Inoltre, devDependencies non viene installato in modo transitorio dai pacchetti dipendenti. Esempio: il pacchetto A dipende dal pacchetto B. Il pacchetto B dipende dal pacchetto C e B anche devDipende dal pacchetto D. Se si esegue npm installdal pacchetto A, si otterranno B e C ma non D.
Ben Hutchison,

9
È importante notare che devDependenciesnon sono installati quando NODE_ENVè impostato su production.
Augusto Franzoia,

491

Se non si desidera installare devDependencies, è possibile utilizzare npm install --production


1
npm install --save è per la dipendenza dal software?
Vamsi Pavan Mahesh,

19
npm install installerà tutte le dipendenze. --save flag viene utilizzato quando si desidera aggiungere anche il modulo specifico a package.json. es: - npm install uglify --save installerà uglify nella cartella del progetto e aggiungerà uglify al progetto, file package.json.
Gayan Charith,

6
E poiché stiamo parlando di devDependencies, puoi usare --save-dev per salvare il nuovo modulo come devDependency. Esempio: npm install uglify --save-dev
Mykaelos

9
A partire da npm 5, l' --saveopzione non è più necessaria. Se fai "npm install my-package", aggiungerà my-package come dipendenza nel tuo package.jsonfile.
Martin Carel,

installa solo npm
sultan aslam l'

116

Ad esempio, la moka sarebbe normalmente una devDependency, poiché i test non sono necessari in produzione, mentre express sarebbe una dipendenza.


4
Mi spingerei a mettere i test come una dipendenza poiché potresti voler eseguire test automatici prima di avviare il server di produzione

47
Vorrei invece raccomandare di utilizzare un servizio di integrazione continua come Hudson o CircleCI che esegue i test e li distribuisce alla produzione se superano.
Dan Kohn,

1
Potrebbe essere ancora rilevante testare il server effettivo perché il server CI potrebbe differire in qualche modo dal server prod, e questa differenza potrebbe, ad esempio, impedire l'avvio dell'app ...
Nicole

2
@Nicole perché dovresti rendere il tuo server di gestione temporanea non identico nella configurazione al tuo prod?
Lucas,

1
Inoltre, l'aggiunta di dipendenze di test come dipendenze regolari introduce un sacco di librerie extra, ognuna delle quali potrebbe non riuscire in qualche modo. Mi sporgerei (gioco di parole!) Verso server di produzione leggeri con meno codice possibile su di essi. Ricorda, il codice migliore non è un codice!
Stijn de Witt,

69

dipendenze
Dipendenze che il progetto deve eseguire, come una libreria che fornisce funzioni chiamate dal proprio codice.
Sono installati in modo transitorio (se A dipende da B dipende da C, npm installa su A installerà B e C).
Esempio: lodash: il tuo progetto chiama alcune funzioni lodash.

devDependencies
Dipendenze necessarie solo durante lo sviluppo o il rilascio, come compilatori che prendono il codice e lo compongono in javascript, framework di test o generatori di documentazione.
Non vengono installati in modo transitorio (se A dipende da B dev-dipende da C, l'installazione di npm su A installa solo B).
Esempio: grunt: il tuo progetto usa grunt per costruirsi.

peerDependencies
Dipendenze che il progetto aggancia o modifica, nel progetto genitore, di solito un plug-in per qualche altra libreria o strumento. È inteso solo come un controllo, assicurandosi che il progetto principale (progetto che dipenderà dal progetto) abbia una dipendenza dal progetto a cui si è collegati. Quindi, se crei un plug-in C che aggiunge funzionalità alla libreria B, allora qualcuno che sta realizzando un progetto A dovrà avere una dipendenza da B se ha una dipendenza da C.
Non sono installati (a meno che npm <3), siano solo verificato per.
Esempio: grunt: il tuo progetto aggiunge funzionalità a grunt e può essere utilizzato solo su progetti che usano grunt.

Questa documentazione spiega molto bene le dipendenze tra pari: https://nodejs.org/en/blog/npm/peer-dependencies/

Inoltre, la documentazione di npm è stata migliorata nel tempo e ora offre spiegazioni migliori dei diversi tipi di dipendenze: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependencies


63

Per salvare un pacchetto in package.json come dipendenze dev:

npm install "$package" --save-dev

Quando npm installlo eseguirai installerai sia devDependenciese dependencies. Per evitare l'installazione, devDependencieseseguire:

npm install --production

3
puoi anche usare: npm i -S
Maysara Alhindi,

36

Ci sono alcuni moduli e pacchetti necessari solo per lo sviluppo, che non sono necessari in produzione. Come si dice nella documentazione :

Se qualcuno sta pianificando di scaricare e utilizzare il modulo nel proprio programma, probabilmente non vuole o non ha bisogno di scaricare e costruire il test esterno o il framework di documentazione che usi. In questo caso, è meglio elencare questi elementi aggiuntivi in ​​un hash devDependencies.


Cosa succede se si esegue solo il file bundle.js in produzione? hai davvero bisogno di quelle dipendenze?
RegarBoy,

Se stai eseguendo bundle.js sul server, stai eseguendo un webpack sul lato server o qualcosa del genere ... Controlla se è così perché di solito non lo è e in realtà ci vuole molto lavoro per farlo funzionare correttamente (I so perché l'ho fatto). Sospetto che bundle.js sia appena offerto ai browser e contenga il codice lato client.
Stijn de Witt,

16

Una semplice spiegazione che mi ha reso più chiaro è:

Quando si distribuisce l'app, è necessario installare i moduli nelle dipendenze o l'app non funzionerà. I moduli in devDependencies non devono essere installati sul server di produzione poiché non si sta sviluppando su quella macchina. collegamento


2
Quindi, se stiamo realizzando un sito Web e nella versione prod, tutte le librerie saranno incorporate vendor.js, tutti i nostri deps dovrebbero essere deps de se il codice compilato viene inserito nel repository? E dovrebbe essere commesso, dato che è strano che sia necessario compilare il modulo, non solo installarlo (e il test è anche da qualche parte qui poiché qualsiasi cambiamento nei sottomoduli può portare alla regressione) ...
Qwertiy

Risposta fantastica, ma c'è una domanda? Il Webpack possibile crea un bundle danneggiato? Suppongo che i pacchetti devDependencies non funzioneranno nella versione del prodotto, webpack -pintendo. per favore rispondi alla mia domanda.
Amerllic,

In caso di problemi durante la generazione della produzione, il processo di distribuzione deve essere progettato in modo tale da mostrare errori al momento della creazione e non inviare codice danneggiato alla produzione (ad esempio, è possibile provare Jenkins). Le deviazioni non devono comunque essere installate sul server di produzione.
Jyoti Duhan,

e che dire delle dipendenze tra pari?
dev27

13

Vorrei aggiungere alla risposta la mia opinione su queste spiegazioni delle dipendenze

  • dependencies sono usati per un uso diretto nella tua base di codice, cose che di solito finiscono nel codice di produzione o pezzi di codice
  • devDependencies sono usati per il processo di compilazione, strumenti che ti aiutano a gestire come andrà a finire il codice finale, moduli di test di terze parti (es. roba webpack)

Che dire delle risorse css?
Brian Zelip,

8

In breve

  1. Dipendenze : npm install <package> --save-prodinstalla i pacchetti richiesti dall'applicazione nell'ambiente di produzione.

  2. DevDependencies : npm install <package> --save-devinstalla i pacchetti richiesti solo per sviluppo e test locali

  3. Basta digitare npm installinstalla tutti i pacchetti menzionati in package.json

quindi se stai lavorando sul tuo computer locale, digita npm installe continua :)


6

peerDependenciesnon aveva molto senso per me fino a quando non ho letto questo frammento da un post sul blog sull'argomento ciro menzionato sopra :

Ciò di cui [ plug-in ] ha bisogno è un modo per esprimere queste "dipendenze" tra plug-in e il loro pacchetto host. Un modo di dire: "Lavoro solo quando sono collegato alla versione 1.2.x del mio pacchetto host, quindi se mi installi, assicurati che sia accanto a un host compatibile." Chiamiamo questa relazione una dipendenza tra pari.

Il plugin prevede una versione specifica dell'host ...

peerDependenciessono per plugin, librerie che richiedono una libreria "host" per svolgere la loro funzione, ma potrebbero essere state scritte in un momento precedente al rilascio dell'ultima versione dell'host.

Cioè, se scrivo PluginX v1per HostLibraryX v3e andare via, non c'è nessuna garanzia PluginX v1funzionerà quando HostLibraryX v4(o addirittura HostLibraryX v3.0.1) viene rilasciato.

... ma il plugin non dipende dall'host ...

Dal punto di vista del plugin, aggiunge solo funzioni alla libreria host. Non ho davvero "bisogno" dell'host per aggiungere una dipendenza a un plugin, e spesso i plugin non dipendono letteralmente dal loro host. Se non si dispone dell'host, il plug-in non fa nulla di innocuo.

Questo significa che dependenciesnon è proprio il concetto giusto per i plugin.

Ancora peggio, se il mio host fosse trattato come una dipendenza, finiremmo in questa situazione menzionata dallo stesso post sul blog (modificato un po 'per usare l'host e il plug-in composti da questa risposta):

Ma ora, [se trattiamo la versione contemporanea di HostLibraryX come una dipendenza per PluginX,] l'esecuzione dei npm installrisultati nel grafico delle dipendenze impreviste di

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

Lascerò i sottili insuccessi che provengono dal plugin usando un'API [HostLibraryX] diversa dall'applicazione principale per la tua immaginazione.

... e l'host ovviamente non dipende dal plugin ...

... questo è il punto centrale dei plugin. Ora, se l'host fosse abbastanza gentile da includere informazioni sulla dipendenza per tutti i suoi plugin, ciò risolverebbe il problema, ma introdurrebbe anche un nuovo enorme problema culturale : la gestione dei plugin!

Il punto centrale dei plugin è che possono accoppiarsi in modo anonimo. In un mondo perfetto, avere l'host a gestirli tutti sarebbe pulito e ordinato, ma non avremo bisogno di librerie e gatti.

Se non siamo gerarchicamente dipendenti, forse siamo colleghi intradipendenti ...

Invece, abbiamo il concetto di essere pari. Né host né plugin si trovano nel bucket delle dipendenze dell'altro. Entrambi vivono allo stesso livello del grafico delle dipendenze.


... ma questa non è una relazione automatizzabile. <<< Moneyball !!!

Se sono PluginX v1e aspetto un peer di (cioè, ho una peerDependency di ) HostLibraryX v3, lo dirò. Se hai eseguito l'upgrade automatico all'ultimo HostLibraryX v4(nota che è la versione 4 ) E hai Plugin v1installato, devi sapere, giusto?

npm non riesco a gestire questa situazione per me -

"Ehi, vedo che stai usando PluginX v1! Sto automaticamente declassando HostLibraryXdalla v4 alla v3, kk?"

... o...

"Ehi, vedo che stai usando PluginX v1. Questo si aspetta HostLibraryX v3, che hai lasciato nella polvere durante il tuo ultimo aggiornamento. Per sicurezza, sto disinstallando automaticamente Plugin v1!! 1!

Che ne dici di no, npm ?!

Quindi npm no. Ti avvisa della situazione e ti consente di capire se HostLibraryX v4è un peer adatto per Plugin v1.


Coda

Una buona peerDependencygestione dei plugin renderà questo concetto più intuitivo nella pratica. Dal post del blog , ancora una volta ...

Un consiglio: i requisiti di dipendenza tra pari, a differenza di quelli per le dipendenze regolari, dovrebbero essere indulgenti. Non è necessario bloccare le dipendenze dei peer fino a versioni di patch specifiche. Sarebbe davvero fastidioso se un plug-in Chai dipendesse da Chai 1.4.1, mentre un altro dipendeva da Chai 1.5.0, semplicemente perché gli autori erano pigri e non passavano il tempo a capire la versione minima effettiva di Chai che sono compatibile con.


4

Dipendenze vs dipendenze degli sviluppatori

Le dipendenze degli sviluppatori sono moduli richiesti solo durante lo sviluppo, mentre le dipendenze sono richieste in fase di esecuzione. Se stai distribuendo la tua applicazione, le dipendenze devono essere installate, altrimenti la tua app semplicemente non funzionerà. Le librerie chiamate dal codice che consentono l'esecuzione del programma possono essere considerate dipendenze.

Ad es. React, React - dom

I moduli di dipendenza degli sviluppatori non devono essere installati nel server di produzione poiché non si svilupperà in quella macchina. I compilatori che convertono il codice in javascript, i framework di test e i generatori di documenti possono essere considerati come dipendenze di sviluppo poiché sono richiesti solo durante lo sviluppo.

Ad esempio ESLint, Babel, webpack

@FYI,

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 pubblichi su npm, è importante utilizzare il flag corretto per i moduli corretti. Se è qualcosa che il tuo modulo npm deve funzionare, usa il flag "--save" per salvare il modulo come dipendenza. Se è qualcosa che il tuo modulo non ha bisogno di funzionare ma è necessario per il test, usa il flag "--save-dev".

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

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

1

Quando si tenta di distribuire un pacchetto npm, è necessario evitare di utilizzarlo dependencies. Invece devi considerare di aggiungerlo peerDependencieso rimuoverlo da dependencies.


1

Ho trovato una semplice spiegazione.

Risposta breve:

dipendenze "... sono quelle di cui il tuo progetto ha davvero bisogno per poter lavorare nella produzione".

devDependencies "... sono quelli di cui hai bisogno durante lo sviluppo."

peerDependencies "se si desidera creare e pubblicare la propria libreria in modo che possa essere utilizzata come dipendenza"

Maggiori dettagli in questo post: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.