В чем разница между зависимостями, devDependencies и peerDependencies в файле npm package.json?

2030

Эта документация очень плохо отвечает на мой вопрос. Я не понял этих объяснений. Кто-то может сказать более простыми словами? Может быть, с примерами, если трудно выбрать простые слова?

EDIT также добавил peerDependencies, что тесно связано и может привести к путанице.

Виталий Корсаков
источник
48
Обратите внимание, есть и optionalDependenciesсейчас.
Эйдан Фельдман
118
@AidanFeldman «опциональные зависимости» - мой оксюморон дня
Ник Булл,
1
Документация npm гласит: «зависимости»: пакеты, необходимые для вашего приложения в производстве. «devDependencies»: пакеты, которые нужны только для локальной разработки и тестирования. см. ссылку: docs.npmjs.com/…
Deke

Ответы:

2367

Резюме важных различий в поведении:

  • 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 не может работать, как и A.

    • devDependenciesне устанавливается транзитивно. Например, нам не нужно тестировать B для тестирования A, поэтому тестовые зависимости B могут быть опущены.

Связанные параметры здесь не обсуждаются:

devDependencies

dependenciesтребуются для запуска, devDependenciesтолько для разработки, например: модульные тесты, преобразование CoffeeScript в JavaScript, минификация, ...

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

npm install

Поскольку у вас есть фактический источник, ясно, что вы хотите его разработать, поэтому по умолчанию также устанавливаются как dependencies(так как вы, конечно, должны работать для разработки), так и devDependencyзависимости.

Однако, если вы только конечный пользователь, который просто хочет установить пакет для его использования, вы будете делать это из любого каталога:

npm install "$package"

В этом случае, вы , как правило , не хотят зависимости развития, так что вы просто получить то , что нужно использовать пакет: dependencies.

Если вы действительно хотите установить пакеты разработки в этом случае, вы можете установить параметр devконфигурации true, возможно, из командной строки:

npm install "$package" --dev

Опция falseпо умолчанию, так как это гораздо менее распространенный случай.

peerDependencies

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

Источник: https://nodejs.org/en/blog/npm/peer-dependencies/

С обычными зависимостями вы можете иметь несколько версий зависимости: она просто устанавливается внутри node_modulesзависимости.

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

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

Плагины, однако, являются пакетами, которые обычно не требуют другого пакета, который в этом контексте называется хостом . Вместо:

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

Например, если dependency1и dependency2peer зависят dependency3, дерево проекта будет выглядеть так:

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

Это происходит, даже если вы никогда не упоминаете dependency3в своем package.jsonфайле.

Я думаю, что это пример шаблона проектирования Inversion of Control .

Прототипом примера одноранговых зависимостей является 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 link или npm install из корня пакета и могут управляться как любой другой параметр конфигурации npm. Смотрите npm-config (7) для более подробной информации по теме.

И тогда под npm-config (7) найдите dev:

Default: false
Type: Boolean

Install dev-dependencies along with packages.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
источник
5
Ах. Я вижу, я неправильно понял. Ваш ответ звучит так, как будто npm install packageэто команда, которую вы будете использовать для установки всех пакетов, которые не являются dev-зависимостями, а не то, что, как я теперь думаю, вы имели в виду, - это «установка пакета под названием [package]», как я и думал. прежде чем читать это. Если бы я был тобой, я бы отредактировал, чтобы сказать [имя-пакета], что ясно показывает, что ты имеешь в виду «вставить-имя-здесь».
Том W
184
Это замечательно! Я так и не понял, но этот ответ научил меня тому, что разница между зависимостями и devDependencies применима только в том случае, если вы собираетесь опубликовать пакет npm. Если вы просто работаете над приложением или сайтом, это не должно иметь большого значения. Спасибо!
jedd.ahyoung
3
Этот пост должен быть обновлен, чтобы отразить измененное peerDependenciesповедение в предстоящем npm @ 3. От blog.npmjs.org/post/110924823920/npm-weekly-5 : «Мы больше не будем автоматически загружать зависимость от однорангового узла. Вместо этого мы будем предупреждать вас, если зависимость от однорангового узла еще не установлена. Это требует от вас разрешать конфликты peerDependency самостоятельно, вручную, но в долгосрочной перспективе это снизит вероятность того, что вы окажетесь в затруднительном положении с зависимостями ваших пакетов. "
nextgentech
8
Кроме того, devDependencies не устанавливаются транзитивно зависимыми пакетами. Пример: пакет A зависит от пакета B. Пакет B зависит от пакета C, и B также devDepends от пакета D. Если вы запускаете npm installиз пакета A, вы получите B и C, но не D.
Бен Хатчисон
9
Важно отметить, что devDependenciesони не установлены, когда NODE_ENVустановлено значение production.
Аугусто Франзойя
491

Если вы не хотите устанавливать devDependencies, вы можете использовать npm install --production

Гаян Чарит
источник
1
npm install --save для программной зависимости?
Вамси Паван Махеш
19
Установка npm установит все зависимости. Флаг --save используется, когда вы хотите добавить определенный модуль также в package.json. пример: - npm install uglify --save установит uglify в папку вашего проекта и добавит uglify в файл project, package.json.
Гаян Чариф
6
И поскольку мы говорим о devDependencies, вы можете использовать --save-dev, чтобы сохранить новый модуль как devDependency. Пример: npm install uglify --save-dev
Mykaelos
9
Начиная с npm 5, --saveопция больше не нужна. Если вы выполните «npm install my-package», он добавит my-package в качестве зависимости в ваш package.jsonфайл.
Мартин Карел
просто установка npm
султан аслам
116

В качестве примера, mocha обычно представляет собой devDependency, поскольку тестирование не требуется в производственной среде, тогда как express будет зависимостью.

Дэн Кон
источник
4
Я бы предпочел поместить тестирование в зависимость, так как вы можете запустить самопроверку перед запуском производственного сервера
47
Вместо этого я бы порекомендовал использовать сервис непрерывной интеграции, такой как Hudson или CircleCI, который запускает ваши тесты, а затем развертывается в рабочем режиме, если они пройдут.
Дэн Кон
1
Возможно, все еще уместно протестировать реальный сервер, поскольку сервер CI может несколько отличаться от сервера prod, и это различие может, например, помешать запуску приложения ...
Николь
2
@ Николь, почему бы тебе сделать свой промежуточный сервер не идентичным по конфигурации своему продукту?
Лукас
1
С другой стороны, добавление тестовых зависимостей в качестве обычных зависимостей вводит целый ряд дополнительных библиотек, каждая из которых может каким-то образом завершиться сбоем. Я бы склонялся (каламбур!) К легким рабочим серверам с минимальным количеством кода на них. Помните, лучший код - это не код!
Стейн де Витт
69

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

devDependencies
Зависимости, которые вам нужны только во время разработки или выпуска, например, компиляторы, которые берут ваш код и компилируют его в javascript, тестовые среды или генераторы документации.
Они не устанавливаются транзитивно (если A зависит от B, dev зависит от C, npm install на A будет устанавливать только B).
Пример: grunt: ваш проект использует grunt для сборки самого себя.

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

Эта документация действительно хорошо объясняет зависимости от сверстников: https://nodejs.org/en/blog/npm/peer-dependencies/

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

qwertzguy
источник
63

Чтобы сохранить пакет в package.json как зависимости dev:

npm install "$package" --save-dev

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

npm install --production
Мохаммед Сейфер
источник
3
Вы также можете использовать: npm i -S
Maysara Alhindi
36

Есть некоторые модули и пакеты, необходимые только для разработки, которые не нужны в производстве. Как сказано в документации :

Если кто-то планирует загрузить и использовать ваш модуль в своей программе, то он, вероятно, не хочет или не нуждается в загрузке и создании используемой вами среды внешнего тестирования или документации. В этом случае лучше перечислить эти дополнительные элементы в хэше devDependencies.

Amberlamps
источник
Что делать, если вы используете только файл bundle.js на производстве? вам действительно нужны эти зависимости?
RegarBoy
Если вы запускаете bundle.js на сервере, вы делаете веб-пакет на стороне сервера или что-то в этом роде ... Пожалуйста, проверьте, так ли это, потому что обычно это не так, и на самом деле требуется много работы, чтобы запустить его правильно (я знаю, потому что я это сделал). Я подозреваю, что ваш bundle.js просто обслуживается браузерами и содержит код на стороне клиента.
Стейн де Витт
16

Простое объяснение, которое сделало его более ясным для меня:

При развертывании приложения необходимо установить модули в зависимостях, иначе ваше приложение не будет работать. Модули в devDependencies не нужно устанавливать на рабочий сервер, так как вы не разрабатываете на этом компьютере. ссылка на сайт

Джоти Духан
источник
2
Итак, если мы делаем сайт и в версии prod все библиотеки будут встроены vendor.js, все наши команды должны быть разработчиками, если скомпилированный код будет добавлен в репозиторий ? И это должно быть зафиксировано, так как в других случаях странно, что вы должны скомпилировать модуль, а не просто установить его (и тестирование также где-то здесь, так как любое изменение в подмодулях может привести к регрессии) ...
Qwertiy
Обалденный ответ, но есть вопрос? Возможно ли в Webpack построить поврежденную связку? Я предполагаю, что пакеты devDependencies не будут работать в версии продукта, webpack -pя имею в виду. пожалуйста, ответь на мой вопрос.
AmerllicA
Если во время производственной сборки возникает какая-либо проблема, процесс развертывания должен быть спроектирован таким образом, чтобы он отображал ошибку во время сборки и не давал поврежденный код в производство (например, вы можете попробовать Jenkins). В любом случае, на рабочем сервере не обязательно устанавливать зависимости.
Джоти Духан
а как насчет равноправных зависимостей?
dev27
13

Я хотел бы добавить к ответу мой взгляд на объяснения этих зависимостей

  • dependencies используются для непосредственного использования в вашей кодовой базе, вещах, которые обычно заканчиваются в производственном коде, или фрагментам кода
  • devDependencies используются для процесса сборки, инструменты, которые помогают вам управлять конечным кодом, сторонние тестовые модули (например, веб-пакеты)
Сырбу Николае-Цезарь
источник
Как насчет активов CSS?
Брайан Зелип
8

Короче говоря

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

  2. DevDependencies - npm install <package> --save-devустанавливает пакеты, необходимые только для локальной разработки и тестирования

  3. Просто печатать npm install установит все пакеты, упомянутые в package.json

так что если вы работаете на локальном компьютере, просто наберите npm installи продолжайте :)

cherankrish
источник
6

peerDependenciesне совсем имело для меня смысл, пока я не прочитал этот фрагмент из поста в блоге на тему Ciro, упомянутую выше :

[ Плагины ] нуждаются в способе выражения этих «зависимостей» между плагинами и их хост-пакетом. Какой-то способ сказать: «Я работаю только при подключении к версии 1.2.x моего хост-пакета, поэтому, если вы устанавливаете меня, убедитесь, что он находится рядом с совместимым хостом». Мы называем эти отношения зависимостью сверстников.

Плагин действительно ожидает конкретную версию хоста ...

peerDependenciesпредназначены для плагинов, библиотек, которым для выполнения своих функций требуется библиотека «хост», но, возможно, они были написаны за время до выпуска последней версии хоста.

То есть, если я пишу PluginX v1для HostLibraryX v3и уйти, нет никакой гарантии , PluginX v1не будет работать , когда HostLibraryX v4(или даже HostLibraryX v3.0.1) освобождается.

... но плагин не зависит от хоста ...

С точки зрения плагина, он только добавляет функции в библиотеку хоста. Мне на самом деле не «нужен» хост, чтобы добавить зависимость к плагину, и плагины часто буквально не зависят от своего хоста. Если у вас нет хоста, плагин безвредно ничего не делает.

Это означает, dependenciesчто на самом деле не правильная концепция для плагинов.

Еще хуже, если бы к моему хосту относились как к зависимости, мы бы оказались в такой ситуации, о которой упоминается в том же посте в блоге (отредактировано немного, чтобы использовать этот ответ, составленный host & plugin):

Но теперь, если мы рассматриваем современную версию 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, кк?»

... или...

"Эй, я вижу, что вы используете PluginX v1. Это ожидает HostLibraryX v3, что вы оставили в пыли во время вашего последнего обновления. На всякий случай, я автоматически удаляю Plugin v1!! 1!

Как насчет нет, нпм ?!

Так что npm не делает. Он предупреждает вас о ситуации и позволяет выяснить, HostLibraryX v4подходит ли вам этот узел Plugin v1.


кода

Хорошее peerDependencyуправление плагинами сделает эту концепцию более интуитивно понятной на практике. Из сообщения в блоге , еще раз ...

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

Ruffin
источник
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.

Melchia
источник
1

Я нашел простое объяснение.

Короткий ответ:

зависимости "... это те, которые ваш проект действительно должен иметь возможность работать в производстве".

devDependencies "... это те, которые вам нужны во время разработки".

peerDependencies "если вы хотите создать и опубликовать свою собственную библиотеку, чтобы она могла использоваться как зависимость"

Более подробно в этом посте: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies

потребности пользователей-помощь
источник