
npm — это инструмент управления пакетами, широко используемый интерфейсными разработчиками. В проекте package.json используется для управления конфигурацией пакетов npm, от которых зависит проект. package.json — это файл json. Помимо описания зависимостей пакетов проекта, он также позволяет нам использовать «правила семантического управления версиями» для указания версий зависимых пакетов вашего проекта, что упрощает обмен вашими сборками с другими разработчиками. повторное использование. Эта статья в основном начинается с недавней практики в сочетании с последними версиями npm и узла, чтобы представить некоторые общие конфигурации в package.json и способы написания стандартизированного package.json.
В проекте nodejs package.json — это файл конфигурации, который управляет его зависимостями. Обычно, когда мы инициализируем проект nodejs, мы передаем:
npm init
, а затем генерируется 3. ваш каталог/файлы, node_modules, package.json и package.lock.json. Содержимое package.json:
{
"name": "Название вашего проекта",
"версия": "1.0.0",
"description": "Описание вашего проекта",
"main": "app.js",
"скрипты": {
"test": "echo "Ошибка: тест не указан" && выход 1",
},
"author": "Имя автора",
"лицензия": "ISC",
"зависимости": {
"dependent1": "^1.4.0",
"зависимость2": "^1.5.2"
}
} Как видно из вышеизложенного, package.json содержит метаданные самого проекта, а также информацию о дополнительных зависимостях проекта (например, зависимости и т. д.).
Мы обнаружили, что во время инициализации npm был сгенерирован не только файл package.json, но и файл package-lock.json. Так почему же нам все равно нужно создавать файл package-lock.json при очистке package.json? По сути, файл package-lock.json предназначен для блокировки версии. Пакет sub-npm, указанный в package.json, имеет следующий вид: React: "^16.0.0". При фактической установке, если версия выше. реагируйте, package.json удовлетворяет требованиям. Это означает, что, согласно одному и тому же файлу package.json, нельзя гарантировать согласованность версий дополнительных зависимостей, установленных дважды.
Файл блокировки пакета показан ниже, а в подзависимости dependency1 подробно указана его версия. Играет роль версии блокировки.
{
"name": "Название вашего проекта",
"версия": "1.0.0",
«lockfileVersion»: 1,
«требуется»: правда,
"зависимости": {
"зависимость1": {
"версия": "1.4.0",
"решено":
"https://registry.npmjs.org/dependent1/-/dependent1-1.4.0.tgz",
"честность":
"sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
},
"зависимость2": {
"версия": "1.5.2",
"решено":
"https://registry.npmjs.org/dependent2/-/dependent2-1.5.2.tgz",
"честность":
"sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ=="
}
}
} . В этой главе речь пойдет о часто используемых атрибутах конфигурации package.json. Такие атрибуты, как имя, версия и т. д., слишком просты и не будут вводиться один за другим. В этой главе в основном представлены свойства скрипта, корзины и рабочих пространств.
использует тег сценария в npm для определения сценария. Всякий раз, когда указан запуск npm, сценарий оболочки будет автоматически создан. Здесь необходимо отметить, что новая оболочка, созданная с помощью запуска npm, будет хранить node_modules/.bin. локальный каталог Добавьте подкаталоги в переменную PATH.
Это означает, что все сценарии в подкаталоге node_modules/.bin текущего каталога можно вызывать напрямую с именем сценария без добавления пути. Например, если зависимости текущего проекта включают esbuild, просто напишите esbuild xxx напрямую.
{
// ...
"скрипты": {
"build": "esbuild index.js",
}
} {
// ...
"скрипты": {
"build": "./node_modules/.bin/esbuild index.js"
}
} Вышеупомянутые два способа записи эквивалентны.
Атрибут bin используется для загрузки исполняемых файлов в глобальную среду. После указания пакета npm с полем bin он будет загружен в глобальную среду, и файл можно будет выполнить через псевдоним.
Например, пакет npm @bytepack/cli:
"bin": {
"bytepack": "./bin/index.js"
}, как только @bytepack/cli будет установлен глобально, вы сможете напрямую выполнить соответствующую команду через bytepack, например
bytepack -v //Показать 1.11.0.
Если он не установлен глобально, он будет автоматически подключен к каталогу node_module/.bin проекта. В соответствии с тем, что было сказано в теге сценария, представленном ранее, его можно использовать напрямую с псевдонимами.
Когда проект слишком велик, в последнее время монорепо становится все более популярным. Когда дело доходит до монорепо, мы не рассматриваем рабочие пространства. Раньше мы использовали рабочие пространства Yarn. Теперь npm официально поддерживает рабочие пространства. Workspaces решает проблему управления несколькими подпакетами в корневом пакете верхнего уровня. в локальной файловой системе. В каталоге объявлений рабочих пространств. Пакет будет мягко связан с node_modules корневого пакета верхнего уровня.
Проиллюстрируем непосредственно примером с официального сайта:
{
"name": "мой-проект",
"рабочие места": [
"пакеты/а"
]
} В пакете npm с именем my-project есть каталог, настроенный для рабочих областей.
. +-- package.json +-- index.js `-- пакеты +-- а `-- package.json
и корневой пакет верхнего уровня с именем my-project имеет подпакет packages/a. В настоящее время, если мы установим npm, пакет npm a, установленный в node_modules в корневом пакете, указывает на локальный пакет /a
. +-- node_modules `-- пакеты/а -> ../пакеты/а | +-- пакет-lock.json +-- package.json `-- пакеты +-- а | `-- package.json
выше --
packages/a -> ../packages/a
относится к программной ссылке из node_modules на локальный пакет npm
Общие среды с атрибутами, связанными со средой package.json, в основном выше, разделен на две категории: среда браузера и узла. Далее давайте посмотрим на свойства конфигурации, связанные со средой в package.json. Определение среды можно просто понять следующим образом:
js включает модули commonjs, CMD, UMD, AMD и ES. Сначала в узле поддерживалось только поле commonjs. Однако, начиная с node13.2.0, node официально поддерживает спецификацию модуля ES. Поле можно использовать в package.json для объявления модульной спецификации, которой следует пакет npm.
//package.json
{
name: "какой-то пакет",
тип: "модуль"||"commonjs"
} Следует отметить, что
если тип не указан, значением типа по умолчанию является commonjs. Однако рекомендуется, чтобы все пакеты npm указывали тип.
Если в поле типа указано значение модуля, используется спецификация ESModule
. поле типа указано, все файлы .js в каталоге будут использоваться. Файлы, оканчивающиеся на суффикс, соответствуют спецификации модуляции, указанной типом.
В дополнение к типу, который может указывать спецификацию модульности, спецификация модуляции, за которой следует файл, указывается через. суффикс файла. Файлы, оканчивающиеся на .mjs, соответствуют используемым спецификациям ESModule. Окончание .cjs соответствует спецификации commonjs
В дополнение к типу package.json также имеет три поля: основное, модуль и браузер
.чтобы определить входной файл пакета npm.
посмотрим на сценарии использования этих трех полей и приоритеты, когда эти три поля существуют одновременно. Предположим, есть пакет npm под названием demo1,
----- dist |-- index.browser.js |-- index.browser.mjs |-- index.js |--
package.json файла index.mjs определяет три поля: main, modul и Browser одновременно,
"main": "dist/index.js", // main
"модуль": "dist/index.mjs", // модуль
// браузер может быть определен как объект сопоставления, соответствующий полю main/module, или он может быть определен непосредственно как строка "browser": {
"./dist/index.js": "./dist/index.browser.js", // браузер+cjs
"./dist/index.mjs": "./dist/index.browser.mjs" // браузер+mjs
},
// "browser": "./dist/index.browser.js" // Браузер создается и используется по умолчанию. Например, если мы ссылаемся на этот пакет npm в проекте:
импортируйте демо из 'demo'
После сборки вышеуказанного. код через инструмент сборки, модуль. Последовательность загрузки:
браузер+mjs > модуль > браузер+cjs > main.
Эта последовательность загрузки является последовательностью загрузки по умолчанию для большинства инструментов сборки, таких как webapck, esbuild и т. д. Этот порядок загрузки можно изменить с помощью соответствующей конфигурации, но в большинстве сценариев мы по-прежнему будем следовать порядку загрузки по умолчанию.
Если поле экспорта определено в package.json, то содержимое, определенное в этом поле, является реальным и полным экспортом пакета npm, и приоритет будет выше, чем у полей main и file.
Например:
{
"имя": "упаковка",
"экспорт": {
".": "./main.mjs",
"./foo": "./foo.js"
}
} import { Something } from "pkg"; // from "pkg/main.mjs" const { Something } = require("pkg/foo" // require("pkg/foo.js") из приведенного выше примера. Кажется, что экспорт может определять экспорт по разным путям. Если экспорты существуют, ранее действительный каталог файлов будет недействителен везде, например, require('pkg/package.json'), поскольку он не указан в экспорте, и будет сообщено об ошибке.
Еще одна важная особенность экспорта — условная ссылка. Например, мы можем указать пакеты npm для ссылки на разные входные файлы на основе разных методов ссылки или модульных типов.
// пакет.json
{
"name":"упаковка",
"main": "./main-require.cjs",
"экспорт": {
"import": "./main-module.js",
"require": "./main-require.cjs"
},
"тип": "модуль"
} В приведенном выше примере, если мы
ссылаемся на «./main-require.cjs»
черезconst p = require('pkg') . Если вы пройдете:
import p from 'pkg',
ссылка будет "./main-module.js"
. Последнее, на что следует обратить внимание: если атрибут экспорта существует, атрибут экспорта будет не только иметь более высокий приоритет, чем основной. но также выше, чем поля модуля и браузера.
Свойства конфигурации, связанные с зависимостями, в package.json включают в себя зависимости, devDependency, PeerDependities, PeerDependancesMeta и т. д.
Зависимости — это зависимости проекта, а devDependency — это модули, необходимые для разработки, поэтому мы можем устанавливать их по мере необходимости в процессе разработки, чтобы повысить эффективность нашей разработки. Что здесь нужно отметить, так это стараться максимально стандартно использовать их в своих проектах. Например, webpack, Babel и т. д. — это зависимости разработки, а не зависимости самого проекта. Не помещайте их в зависимости.
зависимости Помимо зависимостей и devDependency, в этой статье основное внимание уделяется PeerDependency и PeerDependencyMeta.
PeerDependities — это зависимости в package.json, которые могут решить проблему многократной загрузки основной библиотеки и унификации версии основной библиотеки.
//пакет/упаковка -----node_modules |-- npm-a -> Зависит от реакции, реакции-дома |-- npm-b -> Зависит от реакции, реакции-дома |-- index.js
Например, в приведенном выше примере, если пакеты суб-npm a и b происходят из реакции и реакции-дома, то если мы объявим PeerDependicies в package.json пакетов суб-npm a и б, соответствующие зависимости не будут переустановлены.
Следует отметить два момента:
"peerDependities": {.
"реагировать": "^16.8.3 || ^17 || ^18"
},
"peerDependencyMeta": {
"реакция-дом": {
«необязательно»: правда
},
"реагировать-родной": {
«необязательно»: правда
}
} «react-dom» и «react-native» указаны здесь в peerDependencyMeta и являются необязательными, поэтому, если «react-dom» и «react-native» не установлены в проекте, об ошибке не будет сообщено.
Стоит отметить, что мы действительно сняли ограничение через PeerDependencyMeta, но часто бывают сценарии, когда это либо A, либо B. Например, в приведенном выше примере нам нужны «react-dom» и «react-native». и нам нужно его установить, но на самом деле мы не можем добиться этого приглашения с помощью приведенного выше утверждения.
В package.json также имеется множество сторонних атрибутов, таких как типы, используемые в tsc, побочные эффекты, используемые в инструментах сборки, хаски, используемый в git, и eslintIgnore, используемый в eslint. Их конфигурация. Расширения предназначены для конкретных инструментов разработки, и я не буду приводить здесь примеры.