Npm — это инструмент управления пакетами, широко используемый фронтенд-разработчиками. Проект использует package.json для управления конфигурацией пакетов npm, от которых зависит проект. package.json — это файл json. Помимо возможности описания зависимостей пакетов проекта, он позволяет нам использовать «семантические правила версии» для указания версии зависимых пакетов вашего проекта, чтобы вашей сборкой можно было лучше поделиться с другими разработчиками и повторно использовать.
Эта статья в основном начинается с недавней практики в сочетании с последними версиями npm и node, представляет некоторые общие конфигурации в package.json и как написать стандартизированный package.json.
- пакет.json
- общие свойства package.json
- Свойства, связанные со средой package.json
- Свойства, связанные с зависимостями package.json
- Трехсторонний атрибут package.json
пакет.json
Введение в package.json
В проекте nodejs package.json — это файл конфигурации, который управляет его зависимостями. Обычно, когда мы инициализируем проект nodejs, мы передаем:
npm init
Затем в вашем каталоге будут созданы 3 каталога/файла: node_modules, package.json и package.lock.json. Содержимое package.json:
{ "name": "Your project name", "version": "1.0.0", "description": "Your project description", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", }, "author": "Author name", "license": "ISC", "dependencies": { "dependency1": "^1.4.0", "dependency2": "^1.5.2" } }
Как видно из вышеизложенного, package.json содержит метаданные самого проекта, а также информацию о зависимостях проекта (например, зависимости и т. д.).
пакет-lock.json
Мы обнаружили, что при инициализации npm генерируется не только файл package.json, но и файл package-lock.json. Так почему же необходимо генерировать файл package-lock.json, когда package.json очищен? По сути, файл package-lock.json предназначен для блокировки версии. Пакет sub-npm, указанный в package.json, например: react: «¹⁶.0.0», в фактической установке, если версия выше, чем react, удовлетворяет требованиям package.json. Таким образом, в соответствии с одним и тем же файлом package.json, не может быть гарантирована согласованность версий зависимостей двух установок.
Файл package-lock выглядит следующим образом, а подзависимость dependency1 подробно указывает его версию. Играйте роль блокировки версии.
{ "name": "Your project name", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "dependency1": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/dependency1/-/dependency1-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "dependency2": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/dependency2/-/dependency2-1.5.2.tgz", "integrity": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==" } } }
общие свойства package.json
В этой главе мы поговорим о часто используемых атрибутах конфигурации в package.json. Такие атрибуты, как имя и версия, слишком просты, чтобы вводить их по одному. В этой главе в основном представлены атрибуты script, bin и workspaces.
сценарий
Используйте теги сценариев в npm для определения сценариев. Всякий раз, когда указан запуск npm, сценарий оболочки будет создан автоматически. Здесь следует отметить, что новая оболочка, созданная с помощью npm run, сохранит подкаталог node_modules/.bin локального каталога. Добавьте переменную PATH.
Это означает, что все скрипты в подкаталоге node_modules/.bin текущего каталога могут вызываться напрямую с именем скрипта без добавления пути. Например, если в зависимостях текущего проекта есть esbuild, просто напишите напрямую esbuild xxx.
{ // ... "scripts": { "build": "esbuild index.js", } } { // ... "scripts": { "build": "./node_modules/.bin/esbuild index.js" } }
Вышеупомянутые два способа написания эквивалентны.
мусорные ведра
Атрибут bin используется для загрузки исполняемых файлов в глобальную среду. Пакет npm, в котором указано поле bin, будет загружен в глобальную среду после его глобальной установки, и файл можно будет выполнить через псевдоним.
For example, the npm package of \@bytepack/cli: "bin": { "bytepack": "./bin/index.js" },
После глобальной установки @bytepack/cli вы можете выполнять соответствующие команды непосредственно через bytepack, например
bytepack -v //show 1.11.0
Если он не установлен глобально, он будет автоматически подключен к каталогу node_module/.bin проекта. В соответствии с тем, что было сказано в теге script, представленном ранее, его можно использовать непосредственно с псевдонимом.
рабочие пространства
Когда проект слишком велик, монорепозиторий в последнее время становится все более популярным. Когда дело доходит до монорепозитория, мы не хотим смотреть на рабочие пространства. В первые дни мы использовали рабочие области пряжи. Теперь npm официально поддерживает рабочие пространства. Workspaces решает проблему управления несколькими подпакетами в корневом пакете верхнего уровня в локальной файловой системе. В каталоге объявления рабочих областей пакет будет связан с node_modules корневого пакета верхнего уровня.
Непосредственно используйте пример официального веб-сайта, чтобы проиллюстрировать:
{ "name": "my-project", "workspaces": [ "packages/a" ] }
В пакете npm с именем my-project есть каталог конфигурации рабочих пространств.
. +-- package.json +-- index.js `-- packages +-- a | `-- package.json
И самый верхний корневой пакет с именем my-project имеет пакеты/подпакет. На этом этапе, если мы устанавливаем npm, то пакет npm a, установленный в node_modules в корневом пакете, указывает на локальный package/a.
. +-- node_modules | `-- packages/a -> ../packages/a +-- package-lock.json +-- package.json `-- packages +-- a | `-- package.json
вышеупомянутый
-- packages/a -> ../packages/a
Относится к программной ссылке из ссылки в node_modules на локальный пакет npm.
Свойства, связанные со средой package.json
Общие среды в основном делятся на две категории: браузер браузера и среда узла. Далее давайте взглянем на свойства конфигурации, связанные со средой в package.json. Определение среды можно просто понять следующим образом:
- Среда браузера: например, есть некоторые глобальные переменные, которые существуют только в браузере, такие как окно, документ и т. д.
- Среда узла: в исходном файле пакета npm есть некоторые переменные, встроенные пакеты и встроенные функции, которые существуют только в среде узла.
тип
Модульная спецификация js включает модули commonjs, CMD, UMD, AMD, ES и т. д. Самая ранняя поддержка в узле — это только поле commonjs, но, начиная с node13.2.0, узел официально поддерживает спецификацию модуля ES в пакете. В json поле типа можно использовать для объявления модульной спецификации, которой следует пакет npm.
//package.json { name: "some package", type: "module"||"commonjs" }
нужно знать, это:
- Если тип не указан, значением по умолчанию для типа является commonjs, но рекомендуется, чтобы все пакеты npm указывали тип
- Когда заданное значение поля типа является модулем, принимается спецификация ESModule.
- Когда указано поле типа, все файлы, заканчивающиеся суффиксом .js в каталоге, следуют модульной спецификации, указанной типом.
- В дополнение к типу, который может указывать модульную спецификацию, модульная спецификация, которой следует файл, определяется суффиксом файла. Файл, заканчивающийся на .mjs, является используемой спецификацией ESModule, а файл, заканчивающийся на .cjs, соответствует спецификации commonjs.
основной и модуль и браузер
В дополнение к типу в package.json есть три поля: main, module и browser, для определения входного файла пакета npm.
- main : определяет входной файл пакета npm, который можно использовать как в среде браузера, так и в среде узла.
- модуль: входной файл спецификации ESM, который определяет пакет npm, можно использовать как среду браузера, так и среду узла.
- browser : определите файл входа пакета npm в среде браузера.
Давайте посмотрим на сценарии использования этих 3 полей и приоритет, когда эти 3 поля существуют одновременно. Мы предполагаем, что есть пакет npm demo1,
----- dist |-- index.browser.js |-- index.browser.mjs |-- index.js |-- index.mjs
Три поля main, module и browser указаны в его package.json одновременно.
"main": "dist/index.js", // main "module": "dist/index.mjs", // module // browser can be defined as a mapping object that corresponds to the main/module field one-to-one, or it can be directly defined as a string "browser": { "./dist/index.js": "./dist/index.browser.js", // browser+cjs "./dist/index.mjs": "./dist/index.browser.mjs" // browser+mjs }, // "browser": "./dist/index.browser.js" // browser
Создан и используется по умолчанию, например, мы ссылаемся на этот пакет npm в проекте:
import demo from 'demo'
После сборки приведенного выше кода с помощью инструмента сборки последовательность загрузки модуля следующая: _ браузер+mjs › модуль › браузер+cjs › main _ Эта последовательность загрузки является последовательностью загрузки по умолчанию для большинства инструментов сборки, таких как как webapck, esbuild и т. д. Этот порядок загрузки можно изменить с помощью соответствующей конфигурации, но в большинстве случаев мы по-прежнему будем следовать порядку загрузки по умолчанию.
экспорт
Если поле экспорта определено в package.json, то содержимое, определяемое этим полем, является реальным и всем экспортом пакета npm, и приоритет будет выше, чем у основного и файлового полей. например:
{ "name": "pkg", "exports": { ".": "./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 для ссылки на разные файлы записей в соответствии с разными методами ссылок или модульными типами.
// package.json { "name":"pkg", "main": "./main-require.cjs", "exports": { "import": "./main-module.js", "require": "./main-require.cjs" }, "type": "module" }
В приведенном выше примере, если мы передаем
const p = require('pkg')
Ссылка «./main-require.cjs». Если прошло:
import p from 'pkg'
Ссылка «./main-module.js». И последнее, на что следует обратить внимание: если есть атрибут экспорта, атрибут экспорта не только имеет более высокий приоритет, чем основной, но и более высокий, чем поля модуля и браузера.
Свойства, связанные с зависимостями package.json
Свойства конфигурации, связанные с зависимостями, в package.json включают зависимости, devDependencies, peerDependencies и peerDependenciesMeta.
Зависимости — это зависимости проекта, а devDependencies — это модули, необходимые для разработки, поэтому мы можем установить то, что нам нужно в процессе разработки, чтобы повысить эффективность нашей разработки. Здесь следует отметить, что вы должны использовать его как стандарт в своем собственном проекте, например, webpack, babel и т. д., которые являются зависимостями разработки, а не зависимостями самого проекта, и их не следует помещать в зависимости.
Помимо зависимостей и devDependencies, в этой статье основное внимание уделяется peerDependencies и peerDependenciesMeta.
одноранговые зависимости
peerDependencies — это зависимость в package.json, которая может решить проблему многократной загрузки основной библиотеки и унификации версии основной библиотеки.
//package/pkg ----- node_modules |-- npm-a -> rely react,react-dom |-- npm-b -> rely react,react-dom |-- index.js
Например, в приведенном выше примере, если пакеты sub-npm a и b получены из react и react-dom, если мы объявим PeerDependencies в package.json пакетов sub-npm a и b, соответствующие зависимости не будут переустановлены. . Следует отметить два момента:
- Для пакета sub-npm a в npm7, если sub-npm a установлен отдельно, будут установлены пакеты в его peerDependencies. Но это не будет работать до npm7.
- Укажите стандартизированную и подробную конфигурацию PeerDependencies. Я вижу некоторые библиотеки компонентов реакции, которые не указывают реакцию и реакцию-дом в PeerDependencies или помещают реакцию и реакцию-дом в зависимости. Эти две нестандартные спецификации будут существовать. некоторые проблемы.
- Во-вторых, правильно укажите версию пакета npm в PeerDependencies, react-focus-lock\@2.8.1[1] , peerDependencies укажите: «реагировать»: «¹⁶.8.0 || ^17.0.0 || ^ 18.0.0», но на самом деле этот react-focus-lock не поддерживает 18.x react
peerDependenciesMeta
Видеть «Мета» означает метаданные. Здесь peerDependenciesMeta предназначена для детального изменения peerDependencies. Например, в package.json в npm-пакете react-redux есть такой абзац:
"peerDependencies": { "react": "^16.8.3 || ^17 || ^18" }, "peerDependenciesMeta": { "react-dom": { "optional": true }, "react-native": { "optional": true } }
Здесь «react-dom» и «react-native» указаны в peerDependenciesMeta и являются необязательными, поэтому, если проект обнаружит, что «react-dom» и «react-native» не установлены, об ошибке не будет сообщено.
Стоит отметить, что через peerDependenciesMeta мы действительно сняли ограничение, но часто бывают сценарии, где используется либо A, либо B. Например, в приведенном выше примере нам нужны «react-dom» и «react-native». Его нужно установить, но на самом деле из-за приведенного выше утверждения мы не можем реализовать это приглашение.
Трехсторонний атрибут package.json
В package.json также есть много трехсторонних атрибутов, таких как типы, используемые в tsc, sideEffects, используемые в инструментах сборки, husky, используемый в git, eslintIgnore, используемый в eslint, эти расширенные конфигурации имеют значение для конкретных инструментов разработки. Не приводить примеры по одному. один
Дополнительные материалы на PlainEnglish.io.
Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .