Jaka jest różnica między zależnościami, devDependencies i peerDependencies w pliku npm package.json?


2026

Ta dokumentacja bardzo słabo odpowiada na moje pytanie. Nie zrozumiałem tych wyjaśnień. Czy ktoś może powiedzieć prostszymi słowami? Może z przykładami, jeśli trudno jest wybrać proste słowa?

Dodano również EDITpeerDependencies , który jest ściśle powiązany i może powodować zamieszanie.


48
Uwaga, są też optionalDependenciesteraz.
Aidan Feldman

118
@AidanFeldman „opcjonalneDzależności” to mój oksymoron dnia
Nick Bull

1
Dokumentacja npm mówi: „zależności”: pakiety wymagane przez twoją aplikację w środowisku produkcyjnym. „devDependencies”: pakiety potrzebne tylko do lokalnego rozwoju i testowania. patrz link: docs.npmjs.com/…
Deke

Odpowiedzi:


2360

Podsumowanie ważnych różnic w zachowaniu:

  • dependencies są zainstalowane na obu:

    • npm install z katalogu zawierającego package.json
    • npm install $package w dowolnym innym katalogu
  • devDependencies są:

    • również zainstalowany w npm installkatalogu, który zawiera package.json, chyba że podasz --productionflagę (idź głosować odpowiedź Gayana Charitha ).
    • niezainstalowany w npm install "$package"żadnym innym katalogu, chyba że dasz mu taką --devopcję.
    • nie są instalowane przejściowo.
  • peerDependencies:

    • przed wersją 3.0: są zawsze instalowane, jeśli ich brakuje, i zgłaszają błąd, jeśli wiele niezgodnych wersji byłoby używanych przez różne zależności.
    • oczekuje się, że zacznie się od 3.0 (niesprawdzone): ostrzeż, jeśli go nie npm installmasz, i musisz samodzielnie rozwiązać zależność. Podczas działania, jeśli brakuje zależności, pojawia się błąd (wspomniany przez @nextgentech )
  • Przechodniość (wspomniany przez Ben Hutchison ):

    • dependencies są instalowane przejściowo: jeśli A wymaga B, a B wymaga C, wówczas C instaluje się, w przeciwnym razie B nie mógłby działać, a także A.

    • devDependenciesnie jest instalowany tranzytowo. Np. Nie musimy testować B, aby przetestować A, więc zależności testowe B można pominąć.

Powiązane opcje nie omówione tutaj:

devDependencies

dependenciessą wymagane do uruchomienia, devDependenciestylko w celu opracowania, np .: testów jednostkowych, transpozycji CoffeeScript na JavaScript, minimalizacji, ...

Jeśli masz zamiar opracować pakiet, pobierz go (np. Przez git clone), przejdź do jego katalogu głównego zawierającego package.jsoni uruchom:

npm install

Ponieważ masz rzeczywiste źródło, jasne jest, że chcesz je opracować, więc domyślnie instalowane są zarówno dependencies(ponieważ oczywiście musisz uruchomić, aby się rozwijać), jak i devDependencyzależności.

Jeśli jednak jesteś tylko użytkownikiem końcowym, który chce tylko zainstalować pakiet, aby z niego skorzystać, zrobisz to z dowolnego katalogu:

npm install "$package"

W takim przypadku zwykle nie chcą zależności rozwoju, więc po prostu to, co jest potrzebne do korzystania z pakietu: dependencies.

Jeśli naprawdę chcesz w takim przypadku zainstalować pakiety programistyczne, możesz ustawić devopcję konfiguracji na true, być może z wiersza poleceń, jako:

npm install "$package" --dev

Opcja jest falsedomyślnie, ponieważ jest to znacznie mniej powszechny przypadek.

peerDependencies

(Testowany przed 3.0)

Źródło: https://nodejs.org/en/blog/npm/peer-dependencies/

Dzięki regularnym zależnościom możesz mieć wiele wersji zależności: jest ona po prostu instalowana wewnątrz node_moduleszależności.

Np. Jeśli dependency1i dependency2oba zależą od dependency3różnych wersji, drzewo projektu będzie wyglądać następująco:

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

Wtyczki to jednak pakiety, które zwykle nie wymagają drugiego pakietu, który w tym kontekście jest nazywany hostem . Zamiast:

  • wtyczki są wymagane przez hosta
  • wtyczki oferują standardowy interfejs, którego host oczekuje
  • tylko host będzie wywoływany bezpośrednio przez użytkownika, więc musi istnieć jedna wersja.

Np. Jeśli dependency1i dependency2peer zależą dependency3, drzewo projektu będzie wyglądać następująco:

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

Dzieje się tak, mimo że nigdy nie wspominasz dependency3w package.jsonpliku.

Myślę, że jest to przykład wzorca projektowego Inversion of Control .

Prototypowym przykładem zależności równorzędnych jest Grunt, host i jego wtyczki.

Na przykład we wtyczce Grunt, takiej jak https://github.com/gruntjs/grunt-contrib-uglify , zobaczysz, że:

  • grunt jest peer-dependency
  • jedyne require('grunt')jest poniżej tests/: nie jest faktycznie używane przez program.

Następnie, gdy użytkownik użyje wtyczki, domyślnie będzie wymagał wtyczki od Gruntfiledodając grunt.loadNpmTasks('grunt-contrib-uglify')wiersz, ale gruntużytkownik zadzwoni bezpośrednio.

Nie działałoby to wtedy, gdyby każda wtyczka wymagała innej wersji Grunt.

podręcznik

Myślę, że dokumentacja dość dobrze odpowiada na pytanie, być może nie znasz wystarczająco menedżerów węzłów / innych pakietów. Prawdopodobnie to rozumiem tylko dlatego, że wiem trochę o pakiecie Ruby.

Kluczowa linia to:

Te rzeczy zostaną zainstalowane podczas wykonywania npm link lub instalacji npm z katalogu głównego pakietu i mogą być zarządzane jak każdy inny parametr konfiguracyjny npm. Zobacz npm-config (7), aby uzyskać więcej informacji na ten temat.

A następnie w NPM-config (7) znajdź dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.

5
Ach Widzę, że źle zrozumiałem. Twoja odpowiedź brzmi tak, npm install packagejakbyś był poleceniem, którego użyłbyś do zainstalowania wszystkich pakietów, które nie są zależnościami programistów, a nie tym, co myślę, że miałeś na myśli, czyli „zainstaluj pakiet o nazwie [pakiet]” - tak myślałem, że zadziałało przed przeczytaniem tego. Na twoim miejscu zredagowałbym [nazwa-pakietu], co wyraźnie pokazuje, że masz na myśli „wstaw-nazwa-tutaj”.
Tom W

184
To jest świetne! Nigdy nie zdawałem sobie sprawy, ale ta odpowiedź nauczyła mnie, że różnica zależności od devDependencies ma zastosowanie tylko wtedy, gdy zamierzasz opublikować pakiet npm. Jeśli pracujesz tylko nad aplikacją lub witryną, nie powinno to mieć większego znaczenia. Dzięki!
jedd.ahyoung

3
Ten post powinien zostać zaktualizowany, aby odzwierciedlić zmienione peerDependencieszachowanie w nadchodzącym npm @ 3. From blog.npmjs.org/post/110924823920/npm-weekly-5 : „Nie będziemy już automatycznie pobierać zależności równorzędnych. Zamiast tego ostrzegamy, jeśli zależność równorzędna nie jest jeszcze zainstalowana. To wymaga samodzielnie rozwiązać konflikty peerDependency, ale na dłuższą metę powinno to zmniejszyć prawdopodobieństwo, że znajdziesz się w trudnym miejscu z zależnościami pakietów. ”
nextgentech

8
Ponadto devDependencies nie są instalowane tranzytowo przez pakiety zależne. Przykład: pakiet A zależy od pakietu B. Pakiet B zależy od pakietu C, a B również zależy od pakietu D. Jeśli uruchomisz npm installz pakietu A, dostaniesz B i C, ale nie D.
Ben Hutchison

9
Ważne jest, aby zauważyć, że devDependenciesnie są instalowane, gdy NODE_ENVjest ustawiony na production.
Augusto Franzoia,

490

Jeśli nie chcesz instalować devDependencies, możesz użyć npm install --production


1
instalacja npm - zapisywanie jest zależne od oprogramowania?
Vamsi Pavan Mahesh

19
Instalacja npm zainstaluje wszystkie zależności. Flaga --save jest używana, gdy chcesz dodać określony moduł również do package.json. np .: - npm install uglify --save zainstaluje uglify w folderze projektu i doda uglify do projektu, plik package.json.
Gayan Charith,

6
A ponieważ mówimy o devDependencies, możesz użyć --save-dev, aby zapisać nowy moduł jako devDependency. Przykład: npm install uglify --save-dev
Mykaelos 29.09.16

9
Począwszy od npm 5, --saveopcja nie jest już potrzebna. Jeśli zrobisz „npm install my-package”, doda on mój pakiet jako zależność w twoim package.jsonpliku.
Martin Carel

po prostu zainstaluj npm
sułtan aslam

116

Na przykład mokka zwykle byłaby zależnością dev, ponieważ testowanie nie jest konieczne w produkcji, a ekspres byłaby zależnością.


4
Chciałbym postawić testowanie jako zależność, ponieważ możesz chcieć uruchomić autotesty przed uruchomieniem serwera produkcyjnego

47
Zamiast tego poleciłbym skorzystanie z usługi ciągłej integracji, takiej jak Hudson lub CircleCI, która uruchamia twoje testy, a następnie wdraża je do produkcji, jeśli przejdą pomyślnie.
Dan Kohn

1
Testowanie rzeczywistego serwera może być nadal istotne, ponieważ serwer CI może się nieco różnić od serwera prod, a ta różnica może np. Uniemożliwić uruchomienie aplikacji ...
Nicole

2
@Nicole dlaczego miałbyś sprawić, że twój serwer pomostowy nie byłby identyczny w konfiguracji z twoim prod?
Lucas,

1
Z drugiej strony dodanie zależności testowych jako regularnych zależności wprowadza całą masę dodatkowych bibliotek, z których każda może w jakiś sposób zawieść. Byłbym skłonny (pun!) W kierunku lekkich serwerów produkcyjnych z jak najmniejszą ilością kodu na nich. Pamiętaj, że najlepszy kod to brak kodu!
Stijn de Witt

69

zależności
Zależności, które musi uruchomić projekt, takie jak biblioteka udostępniająca funkcje wywoływane z kodu.
Są instalowane przejściowo (jeśli A zależy od B, zależy od C, npm zainstalowanie na A spowoduje zainstalowanie B i C).
Przykład: lodash: twój projekt wywołuje niektóre funkcje lodash.

devDependencies
Zależności, których potrzebujesz tylko podczas programowania lub wydawania, takie jak kompilatory, które pobierają Twój kod i kompilują go do javascript, środowisk testowych lub generatorów dokumentacji.
Nie są instalowane przejściowo (jeśli A zależy od B dev-zależy od C, npm instalacji na A zainstaluje tylko B).
Przykład: chrząknięcie: twój projekt używa chrząstki do zbudowania siebie.

peerDependencies
Zależności, do których projekt dołącza lub modyfikuje w projekcie nadrzędnym, zwykle wtyczka do innej biblioteki lub narzędzia. Jest to po prostu kontrola, upewniająca się, że projekt nadrzędny (projekt, który będzie zależał od twojego projektu) ma zależność od projektu, do którego się przyłączasz. Więc jeśli stworzysz wtyczkę C, która dodaje funkcjonalność do biblioteki B, to osoba tworząca projekt A będzie musiała mieć zależność od B, jeśli ma zależność od C.
Nie są instalowane (chyba że npm <3), są tylko sprawdzone pod kątem.
Przykład: chrząknięcie: Twój projekt dodaje funkcjonalność do chrząstki i może być używany tylko w projektach, które używają chrząknięcia.

Ta dokumentacja naprawdę dobrze wyjaśnia zależności rówieśników: https://nodejs.org/en/blog/npm/peer-dependencies/

Ponadto dokumentacja npm została z czasem ulepszona, a teraz ma lepsze wyjaśnienia różnych rodzajów zależności: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependencies


63

Aby zapisać pakiet w pliku package.json jako zależności deweloperskie:

npm install "$package" --save-dev

Po uruchomieniu npm installzainstaluje zarówno devDependenciesi dependencies. Aby uniknąć instalacji, devDependenciesuruchom:

npm install --production

3
możesz także użyć: npm i -S
Maysara Alhindi

36

Istnieje kilka modułów i pakietów niezbędnych tylko do programowania, które nie są potrzebne w produkcji. Jak napisano w dokumentacji :

Jeśli ktoś planuje pobrać moduł i używać go w swoim programie, prawdopodobnie nie chce lub nie musi pobierać i nie budować używanego zewnętrznego testu lub struktury dokumentacji. W takim przypadku najlepiej wymienić te dodatkowe elementy w skrócie devDependencies.


Co się stanie, jeśli na produkcji działa tylko plik bundle.js? czy naprawdę potrzebujesz tych zależności?
RegarBoy

Jeśli korzystasz z pliku bundle.js na serwerze, robisz webpack po stronie serwera lub coś w tym rodzaju ... Sprawdź, czy tak jest, ponieważ zwykle tak nie jest, a prawidłowe uruchomienie wymaga dużo pracy (I wiem, bo to zrobiłem). Podejrzewam, że plik bundle.js jest obsługiwany tylko w przeglądarkach i zawiera kod po stronie klienta.
Stijn de Witt

16

Proste wyjaśnienie, które wyjaśniło mi to:

Podczas wdrażania aplikacji należy zainstalować moduły zależne, inaczej aplikacja nie będzie działać. Moduły w devDependencies nie muszą być instalowane na serwerze produkcyjnym, ponieważ nie pracujesz na tym komputerze. połączyć


2
Tak więc, jeśli tworzymy stronę internetową i w wersji prod, wszystkie biblioteki vendor.jslib będą wbudowane w , wszystkie nasze deps powinny być dev deps, jeśli skompilowany kod zostanie wprowadzony do repo? I należy to zatwierdzić, ponieważ inaczej dziwne jest, że musisz skompilować moduł, a nie tylko go zainstalować (a testowanie jest również gdzieś tutaj, ponieważ każda zmiana w podmodułach może prowadzić do regresji) ...
Qwertiy

Świetna odpowiedź, ale jest pytanie? Czy możliwy pakiet WebPack tworzy uszkodzony pakiet? Myślę, że pakiety devDependencies nie będą działać w wersji produktu, webpack -pto znaczy. Proszę odpowiedzieć na moje pytanie.
AmerllicA,

Jeśli podczas kompilacji produkcyjnej wystąpi jakiś problem, proces wdrażania powinien być zaprojektowany w taki sposób, aby wyświetlał błąd w czasie kompilacji i nie wypychał uszkodzonego kodu do produkcji (np. Możesz wypróbować Jenkins). W każdym razie nie trzeba instalować żadnych zależności na serwerze produkcyjnym.
Jyoti Duhan,

a co z zależnościami rówieśników?
dev27

13

Chciałbym dodać do odpowiedzi mój pogląd na te wyjaśnienia zależności

  • dependencies są używane do bezpośredniego użycia w twojej bazie kodu, rzeczy, które zwykle kończą się w kodzie produkcyjnym lub kawałkach kodu
  • devDependencies są używane w procesie kompilacji, narzędzia, które pomagają zarządzać końcowym kodem końcowym, moduły testowe innych firm (np. pakiety webpack)

Co z zasobami css?
Brian Zelip

8

W skrócie

  1. Zależności - npm install <package> --save-prodinstaluje pakiety wymagane przez aplikację w środowisku produkcyjnym.

  2. DevDependencies - npm install <package> --save-devinstaluje pakiety wymagane tylko do lokalnego programowania i testowania

  3. Samo wpisanie npm installpowoduje zainstalowanie wszystkich pakietów wymienionych w pliku package.json

więc jeśli pracujesz na komputerze lokalnym, po prostu wpisz npm installi kontynuuj :)


6

peerDependenciesnie miało dla mnie sensu, dopóki nie przeczytałem tego fragmentu z postu na blogu na wspomniany wyżej Ciro :

To, czego [ wtyczki ] potrzebują, to sposób wyrażenia tych „zależności” między wtyczkami a pakietem hosta. Można powiedzieć: „Pracuję tylko po podłączeniu do wersji 1.2.x mojego pakietu hosta, więc jeśli mnie zainstalujesz, upewnij się, że jest on zgodny z kompatybilnym hostem”. Nazywamy ten związek zależnością rówieśniczą.

Wtyczka oczekuje określonej wersji hosta ...

peerDependenciessą przeznaczone dla wtyczek, bibliotek, które wymagają biblioteki „hosta” do wykonywania swojej funkcji, ale mogły zostać napisane w czasie przed wydaniem najnowszej wersji hosta.

Oznacza to, że jeśli piszę PluginX v1do HostLibraryX v3i odejść, nie ma gwarancji, PluginX v1będzie działać, gdy HostLibraryX v4(lub nawet HostLibraryX v3.0.1) zostanie zwolniony.

... ale wtyczka nie zależy od hosta ...

Z punktu widzenia wtyczki dodaje tylko funkcje do biblioteki hosta. Tak naprawdę nie „potrzebuję” hosta, aby dodać zależność od wtyczki, a wtyczki często nie zależą dosłownie od hosta. Jeśli nie masz hosta, wtyczka nieszkodliwie nic nie robi.

Oznacza to, dependenciesże nie jest to właściwa koncepcja wtyczek.

Co gorsza, jeśli mój host byłby traktowany jako zależność, znaleźlibyśmy się w takiej sytuacji, o której wspomina ten sam blog (nieco zmodyfikowany, aby użyć gotowego hosta i wtyczki z odpowiedzią):

Ale teraz [jeśli traktujemy współczesną wersję HostLibraryX jako zależność dla PluginX], uruchomione npm installwyniki powodują nieoczekiwany wykres zależności

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

Wyobrażam sobie subtelne awarie pochodzące z wtyczki używającej innego interfejsu [HostLibraryX] niż główna aplikacja.

... a host oczywiście nie zależy od wtyczki ...

... o to chodzi w wtyczkach. Teraz, jeśli host był na tyle miły, że zawierał informacje o zależnościach dla wszystkich swoich wtyczek, rozwiązałoby to problem, ale wprowadziłoby także ogromny nowy problem kulturowy : zarządzanie wtyczkami !

Chodzi o to, że wtyczki mogą łączyć się anonimowo. W idealnym świecie zarządzanie nimi przez gospodarza byłoby schludne i uporządkowane, ale nie będziemy wymagać od bibliotek stada kotów.

Jeśli nie jesteśmy hierarchicznie zależni, być może jesteśmy niezależni od siebie ...

Zamiast tego mamy pojęcie bycia rówieśnikami. Ani host, ani wtyczka nie znajdują się w segmencie zależności drugiego. Oba żyją na tym samym poziomie wykresu zależności.


... ale to nie jest związek automatyczny. <<< Moneyball !!!

Jeśli jestem PluginX v1i oczekuję rówieśnika (to znaczy, mam peerDependency of ) HostLibraryX v3, powiem tak. Jeśli automatycznie uaktualnione do najnowszej HostLibraryX v4(uwaga to wersja 4 ) I już Plugin v1zainstalowany, trzeba wiedzieć, prawda?

npm nie mogę poradzić sobie z tą sytuacją -

„Hej, widzę, że używasz PluginX v1! Automatycznie obniżam wersję HostLibraryXz v4 na v3, kk?”

... lub ...

„Hej, widzę, że używasz PluginX v1. Oczekuje tego HostLibraryX v3, co zostawiłeś w pyle podczas ostatniej aktualizacji. Dla bezpieczeństwa automatycznie odinstalowuję Plugin v1!! 1!

Co powiesz na nie, npm ?!

Więc npm nie. Ostrzega o sytuacji i pozwala dowiedzieć się, czy HostLibraryX v4jest odpowiedni dla siebie Plugin v1.


Coda

Dobre peerDependencyzarządzanie wtyczkami sprawi, że ta koncepcja będzie działać bardziej intuicyjnie w praktyce. Z posta na blogu jeszcze raz ...

Jedna rada: wymagania dotyczące wzajemnej zależności, w przeciwieństwie do normalnych zależności, powinny być łagodne. Nie powinieneś blokować zależności równorzędnych do konkretnych wersji łatek. Byłoby naprawdę denerwujące, gdyby jedna wtyczka Chai była zależna od Chai 1.4.1, a inna zależała od Chai 1.5.0, po prostu dlatego, że autorzy byli leniwi i nie spędzali czasu na ustalaniu faktycznej minimalnej wersji Chai, którymi są kompatybilny z.


4

Zależności a zależności deweloperskie

Zależności programistyczne to moduły, które są wymagane tylko podczas programowania, podczas gdy zależności są wymagane w czasie wykonywania. W przypadku wdrażania aplikacji należy zainstalować zależności, w przeciwnym razie aplikacja po prostu nie będzie działać. Biblioteki wywoływane z kodu, które umożliwiają uruchomienie programu, można uznać za zależności.

Np. React, React - dom

Moduły zależności deweloperów nie muszą być instalowane na serwerze produkcyjnym, ponieważ nie będziesz programować na tej maszynie. Kompilatory, które zakrywają twój kod do javascript, frameworków testowych i generatorów dokumentów, mogą być uważane za zależności deweloperów, ponieważ są one wymagane tylko podczas programowania.

Np. 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

Jeśli publikujesz w npm, ważne jest, aby użyć poprawnej flagi dla odpowiednich modułów. Jeśli jest to coś, co twój moduł npm musi funkcjonować, użyj flagi „--save”, aby zapisać moduł jako zależność. Jeśli jest to coś, czego moduł nie musi funkcjonować, ale jest potrzebny do testowania, użyj flagi „--save-dev”.

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

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

1

Podczas próby dystrybucji pakietu npm należy unikać używania dependencies. Zamiast tego należy rozważyć dodanie peerDependencieslub usunięcie go dependencies.


1

Znalazłem proste wyjaśnienie.

Krótka odpowiedź:

zależności „… są tymi, których naprawdę potrzebuje Twój projekt, aby móc pracować w produkcji”.

devDependencies „... to te, których potrzebujesz podczas programowania”.

peerDependencies „jeśli chcesz utworzyć i opublikować własną bibliotekę, aby mogła być używana jako zależność”

Więcej szczegółów w tym poście: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.