Описание зависимостей пакета
Манифест пакета содержит ряд опциональных полей, которые позволяют задавать список зависимостей:
dependencies
,devDependencies
,peerDependencies
,optionalDependencies
.
Каждое из этих полей является JSON-объектом, где в качестве ключа указывается название пакета, а в качестве значения — диапазон версий, которые поддерживаются в вашем проекте.
Пример:
{
"dependencies": {
"lodash": "^4.17.15",
"chalk": "~2.3",
"debug": ">2 <4",
},
}
Давайте рассмотрим назначение каждого поля в отдельности.
dependencies
Поле dependencies
определяет список зависимостей, без которых код вашего проекта не сможет корректно работать. Это главный и основной список зависимостей для библиотек и программ на Node.js. Если в вашем коде есть импорты каких-то сторонних зависимостей, например import { get } from 'lodash'
, то эта зависимость должна быть прописана в поле dependencies
. Ее отсутствие приведет к тому, что при выполнении ваша программа упадет с ошибкой, потому что нужная зависимость не будет найдена.
devDependencies
Поле devDependencies
позволяет задать список зависимостей, которые необходимы только на этапе разработки пакета, но не для выполнения его кода в рантайме. Сюда можно отнести всевозможные инструменты разработки и сборки, такие как typescript, webpack, eslint и прочие. Если ваш пакет будет устанавливаться как зависимость для другого пакета, то зависимости из этого списка установлены не будут.
peerDependencies
Поле peerDependencies
играет особую роль при разработке вспомогательных пакетов для некоторых инструментов и фреймворков. К примеру, если вы пишете плагин для Webpack, то в поле peerDependencies
вы можете указать версию webpack, которую ваш плагин поддерживает.
Если ваш пакет будет установлен в проекте, где указанная зависимость отсутствует, либо условие по версии не удовлетворяется, то менеджер пакетов сообщит разработчику об этом.
При установке вашего пакета зависимости из поля peerDependencies
автоматически не устанавливаются, разработчик должен сам установить их в свой родительский проект, прописав в манифесте своего пакета. Это также гарантирует, что в проекте будет использоваться только одна версия зависимости без дубликатов. Ведь если в проекте будет установлено несколько разных версий, скажем, Webpack, то это может привести к серьезным конфликтам.
optionalDependencies
И последнее поле optionalDependencies
позволяет вам указать некритические зависимости, без которых ваше приложение сможет всё равно выполнять свою работу. Если менеджер пакетов не сможет найти или установить такую зависимость, то он просто проигнорирует её и не вызовет ошибки.
Важно понимать, что ваш код должен корректно реагировать на отсутствие таких зависимостей, например, используя связку try… require… catch
.
Зависимости во front-end проектах
Выше мы рассмотрели четыре способа задания различных зависимостей для вашего проекта. Однако не стоит забывать, что эта система была изначально придумана для приложений и библиотек на Node.js, которые выполняются напрямую на машине пользователя, а не в особой песочнице, коей является браузер. Таким образом, стандарт никак не учитывает особенности разработки front-end приложений.
Если кто-то вам скажет, что один способ определения npm-зависимостей для front-end приложений является правильным, а другой нет, то не верьте: «правильного» способа не существует, потому что такой вариант использования просто не учтен в node и npm.
Однако для удобства работы над front-end приложениями я могу предложить вам проверенный временем и опытом формат определения зависимостей. Но для начала давайте попробуем разобраться, чем отличается front-end проект от проекта на Node.js.
Обычно конечная цель Node.js-разработчика заключается в том, чтобы опубликовать созданный им пакет в npm registry, а уже оттуда этот пакет скачивается, устанавливается и используется пользователем как готовое ПО или как библиотека в составе более сложного продукта. При этом зависимости из поля dependencies
в манифесте пакета устанавливаются в проект конечного пользователя.
В случае же с front-end приложением оно не публикуется в npm registry, а собирается как самостоятельный артефакт (статика) и выгружается, например, на CDN. По-сути, npm во front-end проектах используется только для того, чтобы устанавливать сторонние зависимости. По этой причине в манифесте подобного проекта рекомендуется использовать опцию private: true
, которая гарантирует, что файлы приложения не будут случайно отправлены в публичный npm-registry. Название же и версия самого пакета приложения не имеют смысла, т. к. «снаружи» нигде не используются.
Эта особенность front-end приложений позволяет нам использовать поле dependencies
не совсем по его прямому назначению, а как категорию для того, чтобы разделить список зависимостей на две части: в поле dependencies
вы пишете список прямых зависимостей, которые используются в коде приложения, например, lodash
, react
, date-fns
и т. д., а в поле devDependencies
— зависимости, которые нужны для разработки и сборки приложения: webpack
, eslint
, декларации из пакетов @types
и т. д.
Постойте, но это ведь ничем не отличается от того, как прописываются зависимости для пакетов на Node.js! Да, однако некоторые особо педантичные разработчики могут заявить, что раз сторонние зависимости объединяются в бандл приложения при сборке и фактически не импортируются в рантайме, то они должны находиться в поле devDependencies
. Теперь вы можете аргументировано защитить более практичный подход.