Яка різниця між залежностями, devDependitions та peerDependency у файлі npm package.json?


2026

Ця документація дуже погано відповідає на моє запитання. Я не зрозумів цих пояснень. Чи може хтось сказати простішими словами? Може, з прикладами, якщо важко вибрати прості слова?

Також додано EDITpeerDependencies , яке тісно пов'язане і може спричинити заплутаність.


48
Зауважте, є і optionalDependenciesзараз.
Айдан Фельдман

118
@AidanFeldman "необов'язково" - мій оксиморон дня
Нік Булл,

1
Документація npm говорить: "залежності": Пакети, необхідні вашим додатком у виробництві. "devDependitions": пакети, необхідні лише для локальної розробки та тестування. см посилання: docs.npmjs.com / ...
Deke

Відповіді:


2362

Підсумок важливих відмінностей у поведінці:

  • dependencies встановлюються на обох:

    • npm install з каталогу, який містить package.json
    • npm install $package в будь-якому іншому каталозі
  • devDependencies є:

    • також встановлений npm installу каталозі, який містить package.json, якщо ви не передасте --productionпрапор (перейдіть на відповідь Гаяна Чаріта ).
    • не встановлено в npm install "$package"жодному іншому каталозі, якщо ви не надаєте йому --devможливість.
    • не встановлюються транзитивно.
  • peerDependencies:

    • до 3.0: завжди встановлюються, якщо вони відсутні, і виникають помилки, якщо різні несумісні версії залежності будуть використовуватися різними залежностями.
    • очікується, що стартує 3.0 (неперевірено): подайте попередження, якщо його немає npm install, і вам доведеться вирішувати залежність самостійно вручну. Під час запуску, якщо залежність відсутня, ви отримуєте помилку (згадує @nextgentech )
  • Транзитивність (згадував Бен Хатчісон ):

    • dependencies встановлюються транзитивно: якщо A вимагає B, а B вимагає C, тоді C встановлюється, інакше B не може працювати, і жодне з них не повинно.

    • devDependenciesне встановлено транзитивно. Наприклад, нам не потрібно тестувати B для тестування A, тому залежність від тестування B може бути залишена.

Тут не обговорюються пов'язані варіанти:

devЗалежності

dependenciesїх потрібно запускати, devDependenciesлише для розробки, наприклад: тести для модулів, перетворення кава-скрипту в JavaScript, мінімізація, ...

Якщо ви збираєтесь розробляти пакет, ви завантажуєте його (наприклад, через git clone), переходите до його кореня, який містить package.json, і запускаєте:

npm install

Оскільки у вас є власне джерело, зрозуміло, що ви хочете його розробити, тому за замовчуванням встановлюються і обидва dependencies(оскільки, звичайно, потрібно працювати), і devDependencyзалежності.

Якщо ви лише кінцевий користувач, який просто хоче встановити пакет для його використання, ви зробите це з будь-якого каталогу:

npm install "$package"

У цьому випадку, ви , як правило , не хочуть залежності розвитку, так що ви просто отримати те , що потрібно використовувати пакет: dependencies.

Якщо ви дійсно хочете встановити пакети розробки в цьому випадку, ви можете встановити параметр devконфігурації true, можливо, з командного рядка як:

npm install "$package" --dev

Цей параметр falseза замовчуванням, оскільки це набагато рідший випадок.

peerDependitions

(Протестовано до 3.0)

Джерело: https://nodejs.org/en/blog/npm/peer-dependitions/

За допомогою регулярних залежностей ви можете мати кілька версій залежності: вона просто встановлюється всередині node_modulesзалежності.

Наприклад, якщо dependency1і dependency2обидва залежать від dependency3різних версій, дерево проекту буде виглядати так:

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

Однак плагіни - це пакунки, які зазвичай не потребують іншого пакету, який у цьому контексті називається хостом . Замість цього:

  • хост вимагає плагіни
  • плагіни пропонують стандартний інтерфейс, який хостин хотів знайти
  • тільки хост буде викликаний користувачем безпосередньо, тому повинна бути єдина його версія.

Напр., Якщо залежать dependency1і dependency2однорангові dependency3, дерево проекту буде виглядати так:

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

Це трапляється, навіть якщо ви ніколи не згадуєте dependency3у своєму package.jsonфайлі.

Я думаю, що це зразок схеми дизайну Інверсія управління .

Прототипним прикладом рівних залежностей є Grunt, хост і його плагіни.

Наприклад, на плагіні Grunt типу https://github.com/gruntjs/grunt-contrib-uglify ви побачите, що:

  • grunt є peer-dependency
  • єдине require('grunt')- під tests/: воно фактично не використовується програмою.

Тоді, коли користувач буде використовувати плагін, він неявно вимагатиме від цього модуля Gruntfileдодавання grunt.loadNpmTasks('grunt-contrib-uglify')рядка, але це так, gruntщо користувач буде телефонувати безпосередньо.

Це не працює, якщо для кожного плагіна потрібна інша версія Grunt.

Посібник

Я думаю, що документація відповідає на питання досить добре, можливо, ви не просто знайомі з адміністраторами вузлів / інших пакетів. Я, мабуть, це розумію лише тому, що я знаю трохи про розмножувач Ruby.

Ключовий рядок:

Ці речі будуть встановлені під час встановлення npm-посилання або npm-установки з кореня пакета і ними можна керувати, як і будь-який інший параметр конфігурації npm. Див. Npm-config (7) для отримання додаткової інформації з цієї теми.

А потім під npm-config (7) знайдіть dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.

5
Ага. Я бачу, що я зрозумів неправильно. Ваша відповідь звучить так, ніби npm install packageце команда, яку ви використовуєте для встановлення всіх пакетів, що не є залежними від розробників, а не те, що я зараз думаю, що ви мали на увазі, що було "встановити пакет під назвою [package]", як я вважав, що це працює перш ніж прочитати це. Якби я був ти, я відредагував би сказати [ім'я пакета], що чітко показує, що ти маєш на увазі "вставити-ім'я-сюди".
Tom W

184
Це чудово! Я ніколи не усвідомлював, але ця відповідь навчила мене, що різниця залежностей проти devDependitions застосовна лише в тому випадку, якщо ви збираєтесь опублікувати пакет npm. Якщо ви просто працюєте над додатком або сайтом, це не повинно мати великого значення. Дякую!
jedd.ahyoung

3
Це повідомлення слід оновити, щоб відобразити змінену peerDependenciesповедінку в майбутньому npm @ 3. З blog.npmjs.org/post/110924823920/npm-weekly-5 : "Ми більше не будемо автоматично завантажувати залежність від однорангових. Замість цього ми попередимо вас, якщо однорангова залежність ще не встановлена. Це вимагає від вас Вирішувати конфлікти peerDependency самостійно, вручну, але в кінцевому рахунку це має зменшити ймовірність того, що ви опинитеся в хитрому місці, залежно від пакунків. "
nextgentech

8
Також devDependitions не встановлюються транзитивно залежними пакетами. Приклад: пакет A залежить від пакету B. Пакет B залежить від пакету C, а B також devDeenden від пакету D. Якщо ви запустите npm installз пакета A, ви отримаєте B і C, але не D.
Бен Хатчісон

9
Важливо зауважити, що devDependenciesне встановлено, коли NODE_ENVвстановлено значення production.
Augusto Franzoia

490

Якщо ви не хочете встановлювати devDependitions, ви можете використовувати npm install --production


1
npm install --соба - це залежність від програмного забезпечення?
Вамсі Паван Махеш

19
npm install встановить усі залежності. --save прапор використовується, коли ви також бажаєте додати певний модуль до package.json. Наприклад: - npm install uglify --save встановить uglify у папці вашого проекту та додасть uglify до проекту, файла package.json.
Гаян Чаріт

6
Оскільки ми говоримо про devDependpendes, ви можете використовувати --save-dev для збереження нового модуля як devDependency. Приклад: npm install uglify --save-dev
Mykaelos

9
З npm 5 цей --saveпараметр більше не потрібен. Якщо ви зробите "npm install my-package", він додасть my-package як залежність у вашому package.jsonфайлі.
Мартін Карел

просто npm install
султан

116

Наприклад, мока, як правило, є залежною від devDependence, оскільки тестування не є необхідним у виробництві, тоді як експрес - залежність.


4
Я б схилявся до тестування як до залежності, оскільки ви, можливо, захочете запустити самотести перед тим, як запустити виробничий сервер

47
Я б замість цього рекомендував використовувати послугу безперервної інтеграції на зразок Hudson або CircleCI, яка запускає ваші тести, а потім розгортається до виробництва, якщо вони проходять.
Дан Кон

1
Це все ще може бути актуальним для тестування фактичного сервера, оскільки сервер CI може дещо відрізнятися від сервера prod, і ця різниця може, наприклад, запобігти запуску програми ...
Ніколь,

2
@Nicole, чому б ви зробили ваш сервер постановки не ідентичним конфігурації вашого продукту?
Лукас

1
Потім знову додавання тестових залежностей як звичайних залежностей вводить цілу купу додаткових бібліотек, кожна з яких може певним чином вийти з ладу. Я б схилявся (каламбур) до легких виробничих серверів з якомога меншим кодом на них. Пам'ятайте, найкращий код - це не код!
Штійн де Вітт

69

залежності
Залежності, які потрібно запустити вашому проекту, як бібліотека, яка надає функції, які ви викликаєте зі свого коду.
Вони встановлюються транзитивно (якщо A залежить від B, залежить від C, npm install на A встановить B і C).
Приклад: lodash: ваш проект викликає деякі функції lodash.

devDependpend
Залежності, які вам потрібні лише під час розробки або випуску, як компілятори, які беруть ваш код і компілюють його в javascript, тестові рамки або генератори документації.
Вони не встановлені транзитивно (якщо A залежить від B dev - залежить від C, npm install на A встановить лише B).
Приклад: grunt: ваш проект використовує grunt для створення себе.

peerDependitions
Залежності, які ваш проект залучає або змінює в батьківському проекті, як правило, плагін для якоїсь іншої бібліотеки чи інструменту. Він призначений лише для перевірки, щоб переконатися, що батьківський проект (проект, який буде залежати від вашого проекту) має залежність від проекту, який ви підключите. Отже, якщо ви робите плагін C, який додає функціональність до бібліотеки B, то хтось, хто створює проект A, повинен мати залежність від B, якщо він має залежність від C.
Вони не встановлені (якщо npm <3), вони лише перевірено на.
Приклад: grunt: ваш проект додає функціональність до grunt і може бути використаний лише для проектів, які використовують grunt.

Ця документація дуже добре пояснює залежності від однолітків: https://nodejs.org/en/blog/npm/peer-dependitions/

Крім того, документація на npm була вдосконалена з часом, і тепер є кращі пояснення різних типів залежностей: https://github.com/npm/cli/blob/latest/doc/files/package.json.md#devdependitions


63

Щоб зберегти пакунок до package.json як залежність від розробника:

npm install "$package" --save-dev

При запуску npm installвін встановить і те, devDependenciesі dependencies. Щоб уникнути devDependenciesзапуску встановлення :

npm install --production

3
Ви також можете використовувати: npm i -S
Maysara Alhindi

36

Є деякі модулі та пакети, необхідні лише для розробки, які не потрібні у виробництві. Як це сказано в документації :

Якщо хтось планує завантажувати та використовувати ваш модуль у своїй програмі, він, ймовірно, не хоче або потребує завантаження та створення зовнішнього тестового або документаційного каркасу, який ви використовуєте. У цьому випадку найкраще перерахувати ці додаткові елементи в хеші devDependitions.


Що робити, якщо у виробництві використовується лише файл bundle.js? вам справді потрібні ці залежності?
RegarBoy

Якщо ви використовуєте bundle.js на сервері, ви робите серверний веб-пакет або щось подібне ... Будь ласка, перевірте, чи це так, тому що зазвичай це не так, і для його правильної роботи потрібна велика робота (я знаю, бо я це зробив). Я підозрюю, що ваш bundle.js просто подається до браузерів і містить код на стороні клієнта.
Штійн де Вітт

16

Просте пояснення, яке зрозуміло для мене, це:

Коли ви розгортаєте свою програму, потрібно встановити модулі в залежності, інакше ваш додаток не працюватиме. Модулі в devDependpend не потрібно встановлювати на виробничому сервері, оскільки ви не розробляєте на цій машині. посилання


2
Отже, якщо ми робимо веб-сайт і в prod-версії всі ліб-файли будуть вкладені в vendor.jsусі, наші депси повинні бути dev deps, якщо компільований код заноситься в репо? І це слід зауважити, оскільки іншим дивним є те, що ви повинні компілювати модуль, а не просто його встановлювати (а тестування теж десь тут, оскільки будь-яка зміна підмодулів може призвести до регресії) ...
Qwertiy

Дивовижна відповідь, але є питання? Чи можливий Webpack створити зіпсований пакет? Я думаю, що пакети devDependitions не працюватимуть у версії продукту, webpack -pя маю на увазі. будь ласка, дайте відповідь на моє запитання.
AmerllicA

Якщо під час нарощування виробництва є якісь проблеми, процес розгортання повинен бути розроблений таким чином, щоб він відображав помилки під час збирання і не підштовхував пошкоджений код до виробництва (наприклад, ви можете спробувати Jenkins). Індивідуальні залежності все одно не потрібно встановлювати на виробничому сервері.
Jyoti Duhan

а що з однолітками?
dev27

13

Я хотів би додати у відповідь своє бачення щодо пояснень цих залежностей

  • dependencies використовуються для прямого використання у вашій кодовій базі, речі, які зазвичай закінчуються у виробничому коді, або шматки коду
  • devDependencies використовуються для процесу збирання, інструменти, які допоможуть вам керувати тим, як закінчиться код кінцевого результату, сторонні тестові модулі (наприклад, матеріали веб-упаковки)

Що з активами css?
Брайан Зеліп

8

Коротко

  1. Залежності - npm install <package> --save-prodвстановлює пакети, необхідні вашим додатком у виробничому середовищі.

  2. DevDependitions - npm install <package> --save-devвстановлює пакети, необхідні лише для локальної розробки та тестування

  3. Просто ввівши, npm installвстановіть усі пакунки, згадані в package.json

тому якщо ви працюєте на своєму локальному комп’ютері, просто введіть npm installі продовжуйте :)


6

peerDependenciesне було для мене сенсу, поки я не прочитав цей фрагмент із публікації в блозі на тему Ciro, згадану вище :

Що [ плагіни ] потребують, це спосіб вираження цих "залежностей" між плагінами та їх хост-пакетом. Якийсь спосіб сказати: "Я працюю лише тоді, коли підключений до версії 1.2.x мого хост-пакета, тому якщо ви встановите мене, будьте впевнені, що це поряд із сумісним хостом". Ми називаємо ці відносини однорідними залежностями.

Плагін очікує конкретної версії хоста ...

peerDependenciesпризначені для плагінів, бібліотеки, для виконання яких потрібна бібліотека "хост", але, можливо, вони були написані за час до виходу останньої версії хоста.

Тобто, якщо я пишу PluginX v1для HostLibraryX v3і піти, немає ніякої гарантії , PluginX v1не працюватиме , коли HostLibraryX v4(або навіть HostLibraryX v3.0.1) звільняється.

... але плагін не залежить від хоста ...

З точки зору плагіна, він лише додає функції до хост-бібліотеки. Мені насправді не потрібен хост, щоб додати залежність до плагіна, а плагіни часто буквально не залежать від їх хоста. Якщо у вас немає хоста, плагін нешкідливо нічого не робить.

Це означає dependencies, що насправді не є правильною концепцією для плагінів.

Ще гірше, якби до мого хоста трактувались як до залежності, ми опинимось у такій ситуації, що згадується той самий запис у блозі (трохи відредагований, щоб використати цей відповідь, складений хостом та плагіном):

Але тепер, [якщо ми розглянемо сучасну версію HostLibraryX як залежність від PluginX,] працює npm installрезультати в графіку несподіваної залежності

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

Я залишу тонкі збої, що виникають у плагіні, використовуючи інший API [HostLibraryX], ніж основний додаток для вашої фантазії.

... і хост, очевидно, не залежить від плагіна ...

... у цьому вся суть плагінів. Тепер, якщо хост був досить приємний, щоб включити інформацію про залежність для всіх своїх плагінів, це вирішило б проблему, але це також ввело б величезну нову культурну проблему : управління плагінами!

Вся суть плагінів у тому, що вони можуть з'єднуватися анонімно. У досконалому світі, якщо господарювати з ними господарями, все було б охайно і охайно, але ми не будемо потребувати в бібліотеках стадових котів.

Якщо ми не є ієрархічно залежні, можливо, ми не залежні від однолітків ...

Натомість у нас є концепція бути однолітками. Ні хост, ні плагін не сидять у відрізку залежності іншого. Обидва живуть на одному рівні графіка залежності.


... але це не автоматизовані відносини. <<< Moneyball !!!

Якщо я є PluginX v1і очікую, що рівний (тобто мати рівну залежність ) HostLibraryX v3, я скажу так. Якщо ви автоматично оновили до останнього HostLibraryX v4(зверніть увагу на версію 4 ) І вже Plugin v1встановлена, ви повинні знати, правильно?

npm не вдається вирішити цю ситуацію для мене -

"Гей, я бачу, ти використовуєш PluginX v1! Я автоматично знижую програмуHostLibraryX від v4 до v3, kk?"

... або ...

"Ей, я бачу, ви використовуєте PluginX v1. Це очікує HostLibraryX v3, що ви залишили в пилу під час останнього оновлення. Щоб надійно, я автоматично видаляюPlugin v1 !! 1!

Як щодо ні, npm ?!

Отже, npm - ні. Це сповіщає вас про ситуацію та дає змогу з’ясувати, чи HostLibraryX v4є підходящим ровесником Plugin v1.


Кода

Хороше peerDependencyуправління плагінами змусить цю концепцію працювати більш інтуїтивно на практиці. З публікації щоденника , ще раз ...

Порада: вимоги до рівних залежностей, на відміну від звичайних залежностей, повинні бути поблажливішими. Ви не повинні блокувати свої однорангові залежності до певних версій патчу. Було б дуже прикро, якби один плагін Chai залежав від Chai 1.4.1, а інший залежав від Chai 1.5.0, просто тому, що автори були ліниві і не витратили час на з'ясування фактичної мінімальної версії Chai, яку вони сумісний з.


4

Залежності від dev залежності

Dev залежності - це модулі, які потрібні лише під час розробки, тоді як залежності потрібні під час виконання. Якщо ви розгортаєте свою програму, потрібно встановити залежності, інакше ваш додаток просто не працюватиме. Бібліотеки, до яких ви телефонуєте зі свого коду, що дозволяє програмі запускатись, можуть розглядатися як залежності.

Наприклад, реагувати, реагувати - дом

Модулі залежності Dev не потрібно встановлювати на виробничому сервері, оскільки ви не збираєтесь розробляти на цій машині. Компілятори, які перекривають ваш код у javascript, тестові рамки та генератори документів, можуть розглядатися як dev-залежності, оскільки вони потрібні лише під час розробки.

Наприклад, ESLint, Babel, веб-пакет

@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

Якщо ви публікуєте npm, важливо, щоб ви використовували правильний прапор для правильних модулів. Якщо ваш модуль npm повинен функціонувати, тоді використовуйте прапор "--save", щоб зберегти модуль як залежність. Якщо ваш модуль не потребує функціонування, але він потрібен для тестування, тоді використовуйте прапор "--save-dev".

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

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

1

При спробі розповсюдження пакету npm вам слід уникати використання dependencies. Замість цього вам потрібно розглянути можливість додавання peerDependenciesабо видалення з нього dependencies.


1

Я знайшов просте пояснення.

Коротка відповідь:

залежності "... це ті, що ваш проект дійсно потребує, щоб мати можливість працювати у виробництві".

devDependitions "... це ті, які вам потрібні під час розвитку."

peerDependitions "якщо ви хочете створити та опублікувати власну бібліотеку, щоб її можна було використовувати як залежність"

Більше деталей у цьому дописі: https://code-trotter.com/web/dependency-vs-devdependences-vs-peerdependitions

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.