
Резюме важных различий в поведении:
dependencies установлены на обоих:
npm installиз каталога, содержащегоpackage.jsonnpm install $packageв любом другом каталоге
devDependencies являются:
- также установлен на
npm installв каталоге, содержащемpackage.json, если только вы не передадите флаг--production. - не установлен на
npm install "$package"в любом другом каталоге, если вы не укажете ему опцию--dev. - не устанавливаются транзитивно.
- peerDependencies устанавливаются автоматически, если нет конфликта зависимостей восходящего потока, который не может быть разрешен автоматически.
Транзитивность :
dependenciesустанавливаются транзитивно: если A требует B, а B требует C, то устанавливается C, иначе B не может работать, как и A.devDependenciesне устанавливается транзитивно. Например. нам не нужно тестировать B для тестирования A, поэтому тестовые зависимости B можно опустить.
devDependencies
Источник: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#devdependencies
dependencies необходимы для запуска, devDependencies только для разработки, например: модульные тесты, транспиляция CoffeeScript в JavaScript, минимизация, ...
Если вы собираетесь разработать пакет, вы загружаете его (например, через git clone), переходите в его корень, содержащий package.json, и запускаете:
npm install
Так как у вас есть актуальный исходник, то понятно, что вы хотите его развивать, поэтому по умолчанию также устанавливаются как dependencies (поскольку для разработки надо, конечно, запустить), так и devDependency зависимости.
Однако, если вы являетесь только конечным пользователем, который просто хочет установить пакет для его использования, вы можете сделать это из любого каталога:
npm install "$package"
В этом случае вам обычно не нужны зависимости для разработки, поэтому вы просто получаете то, что необходимо для использования пакета: dependencies.
Если вы действительно хотите установить пакеты разработки в этом случае, вы можете установить для параметра конфигурации dev значение true, возможно, из командной строки следующим образом:
npm install "$package" --dev
Параметр false по умолчанию, так как это гораздо менее распространенный случай.
одноранговые зависимости
Источник: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#peerdependencies
С обычными зависимостями у вас может быть несколько версий зависимости: она просто устанавливается внутри node_modules зависимости.
Например. если dependency1 и dependency2 оба зависят от dependency3 в разных версиях, дерево проекта будет выглядеть так:
root/node_modules/
|
+- dependency1/node_modules/
| |
| +- dependency3 v1.0/
|
|
+- dependency2/node_modules/
|
+- dependency3 v2.0/
Плагины, однако, представляют собой пакеты, которым обычно не требуется другой пакет, который в данном контексте называется host. Вместо:
- подключаемые модули требуются хостом
- плагины предлагают стандартный интерфейс, который хост ожидает найти
- только хост будет вызываться непосредственно пользователем, поэтому должна быть одна его версия.
Например. если dependency1 и dependency2 одноранговые узлы зависят от dependency3, дерево проекта будет выглядеть так:
root/node_modules/
|
+- dependency1/
|
+- dependency2/
|
+- dependency3 v1.0/
Это происходит даже при том, что вы никогда не упоминаете dependency3 в своем файле package.json.
Я думаю, что это пример шаблона проектирования Инверсия управления.
Типичным примером одноранговых зависимостей является Grunt, хост и его плагины.
Например, в плагине Grunt типа https://github.com/gruntjs/grunt-contrib-uglify вы увидите следующее:
gruntis apeer-dependency- единственный
require('grunt')находится подtests/: он фактически не используется программой.
Затем, когда пользователь будет использовать плагин, он неявно потребует плагин из Gruntfile, добавив строку grunt.loadNpmTasks('grunt-contrib-uglify'), но именно grunt пользователь будет вызывать напрямую.
Это бы не сработало, если бы для каждого плагина требовалась своя версия Grunt.
peerDependenciesMeta
Источник: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#peerdependenciesmeta
Когда пользователь устанавливает ваш пакет, npm будет выдавать предупреждения, если пакеты, указанные в peerDependencies, еще не установлены. Поле peerDependenciesMeta служит для предоставления npm дополнительной информации о том, как должны использоваться ваши одноранговые зависимости. В частности, он позволяет помечать одноранговые зависимости как необязательные.
Например:
{
"name": "tea-latte",
"version": "1.3.5",
"peerDependencies": {
"tea": "2.x",
"soy-milk": "1.2"
},
"peerDependenciesMeta": {
"soy-milk": {
"optional": true
}
}
}
Пометка одноранговой зависимости как необязательной гарантирует, что npm не выдаст предупреждение, если пакет soy-milk не установлен на хосте. Это позволяет вам интегрироваться и взаимодействовать с различными хост-пакетами, не требуя их установки.
связанные зависимости
Источник: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#bundleddependencies
Это определяет массив имен пакетов, которые будут объединены при публикации пакета.
В тех случаях, когда вам нужно сохранить пакеты npm локально или сделать их доступными через загрузку одного файла, вы можете объединить пакеты в файл tarball, указав имена пакетов в массиве bundledDependencies и выполнив npm pack.
Например, если мы определим package.json следующим образом:
{
"name": "awesome-web-framework",
"version": "1.0.0",
"bundledDependencies": [
"renderized",
"super-streams"
]
}
мы можем получить файл awesome-web-framework-1.0.0.tgz, запустив npm pack. Этот файл содержит зависимости renderized и super-streams, которые можно установить в новом проекте, выполнив npm install awesome-web-framework-1.0.0.tgz. Обратите внимание, что имена пакетов не включают никаких версий, так как эта информация указана в dependencies.
Если это пишется как "bundleDependencies", то это тоже считается.
необязательные зависимости
Источник: https://docs.npmjs.com/cli/v8/configuring-npm/package-json#Optionaldependencies
Если можно использовать зависимость, но вы хотите, чтобы npm продолжил работу, если ее не удается найти или установить не удается, вы можете поместить ее в объект optionalDependencies. Это сопоставление имени пакета с версией или URL-адресом, как и у объекта dependencies. Разница в том, что сбои сборки не приводят к сбою установки. Запуск npm install --no-optional предотвратит установку этих зависимостей.
Ответственность за отсутствие зависимости по-прежнему лежит на вашей программе. Например, что-то вроде этого:
try {
var foo = require('foo')
var fooVersion = require('foo/package.json').version
} catch (er) {
foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
foo = null
}
// .. then later in your program ..
if (foo) {
foo.doFooThings()
}
Записи в optionalDependencies переопределяют записи с тем же именем в dependencies, поэтому обычно лучше размещать их только в одном месте.
ЗАКЛЮЧЕНИЕ
надеюсь теперь все понятно.
Спасибо, что читаете 🙏.
И если вам понравилось мое объяснение, помните, что хлопать можно больше одного раза 👏.
Хорошего дня