package.json
Файл маніфесту пакунка. Він містить усі метадані пакунка, включно із залежностями, назвою, автором тощо. Це стандарт, який зберігається у всіх основних менеджерах пакунків Node.js, включаючи pnpm.
engines
Ви можете вказати версію Node і pnpm, на якій працює ваше програмне забезпечення:
{
"engines": {
"node": ">=10",
"pnpm": ">=3"
}
}
Під час локальної розробки pnpm завжди завершить роботу з повідомленням про помилку, якщо його версія не збігається з версією, вказаною у полі engines
.
Якщо користувач не встановив прапорець конфігурації engine-stric
(див. .npmrc), це поле є лише рекомендаційним і показуватиме попередження лише тоді, коли ваш пакунок встановлено як залежність.
dependenciesMeta
Додаткова метаінформація, що використовується для залежностей, оголошених всередині dependencies
, optionDependencies
та devDependencies
.
dependenciesMeta.*.injected
Якщо для залежності, яка є пакунком локального робочого простору, встановлено значення true
, цей пакунок буде встановлено шляхом створення копії з жорстким посиланням у віртуальному сховищі (node_modules/.pnpm
).
Якщо цей параметр встановлено у false
або не встановлено, залежність буде встановлено шляхом створення символічного посилання node_modules
, яке вказуватиме на теку з кодом пакунка у робочій області. Це стандартний спосіб, оскі льки він швидший і гарантує, що будь-які зміни в залежності будуть негайно помітні її споживачам.
Наприклад, припустимо, що наступний package.json
є пакунком локального робочого простору:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0"
}
}
Залежність button
зазвичай встановлюється шляхом створення символічного посилання у теці node_modules
теки card
, яке вказує на теку розробки для button
.
Але що, якщо button
вказує react у своїх peerDependencies
? Якщо всі проєкти в монорепо використовують однакову версію react
, то проблеми немає. Але що робити, якщо button
вимагає card
, який використовує react@16
і form
, який використовує react@17
? Зазвичай вам потрібно вибрати одну версію react
і вказати її за допомогою devDependencies
з button
. Створення символічних посилань не дає можливос ті задовольнити залежність react різними споживачами, такими як card
та form
, по-різному.
Поле injected
розвʼязує цю проблему, встановлюючи копії button
у віртуальному сховищі з жорсткими посиланнями. Щоб досягти цього, package.json
для card можна сконфігурувати наступним чином:
{
"name": "card",
"dependencies": {
"button": "workspace:1.0.0",
"react": "16"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
Тоді як package.json
для form можна було б налаштувати наступним чином:
{
"name": "form",
"dependencies": {
"button": "workspace:1.0.0",
"react": "17"
},
"dependenciesMeta": {
"button": {
"injected": true
}
}
}
З цими змінами ми говоримо, що button
є "injected dependency" від card
і form
. Коли button
імпортує react
, він перетвориться на react@16
в контексті card
, але перет вориться на react@17
в контексті form
.
Оскільки інʼєкційні залежності створюють копії теки з вихідним кодом своєї робочої області, ці копії необхідно якось оновлювати щоразу, коли код модифікується; інакше новий стан не буде відображено для споживачів. Якщо ви збираєте декілька проєктів за допомогою команди типу pnpm --recursive run build
, це оновлення має відбуватися після того, як буде зібрано кожен пакунок, але до того, як буде зібрано його споживачів. У простих випадках це можна зробити повторним викликом pnpm install
, можливо, за допомогою сценарію життєвого циклу package.json
, наприклад, "prepare": "pnpm run build"
для перезбірки цього проєкту. Сторонні інструменти, такі як pnpm-sync та pnpm-sync-dependencies-meta-injected надають більш надійне та ефективне рішення для оновлення інʼєкційних залежностей, а також підтримку режиму спостереження.
peerDependenciesMeta
У цьому полі перелічено деяку додаткову інформацію, повʼязану із залежностями, переліченими у полі peerDependencies
.
peerDependenciesMeta.*.optional
Якщо цей параметр встановлено у true, вибрану пряму залежність буде позначено менеджером пакунків як необовʼязкову. Таким чином, якщо споживач пропустить її, це більше не буде вважатися помилкою.
Наприклад:
{
"peerDependencies": {
"foo": "1"
},
"peerDependenciesMeta": {
"foo": {
"optional": true
},
"bar": {
"optional": true
}
}
}
Зауважте, що навіть якщо bar
не було вказано у peerDependencies
, він позначений як необовʼязковий. Таким чином, pnpm буде вважати, що будь-яка версія bar є прийнятною.
Втім, foo
є необовʼязковим, але лише для необхідної специфікації версії.
publishConfig
Можна перевизначити деякі поля в маніфесті до того, як пакунок буде запаковано. Наступні поля можуть бути перевизначені:
Щоб перевизначити поле, додайте версію для публікації до publishConfig
.
Наприклад, наступний package.json
:
{
"name": "foo",
"version": "1.0.0",
"main": "src/index.ts",
"publishConfig": {
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
}
Буде опубліковано як:
{
"name": "foo",
"version": "1.0.0",
"main": "lib/index.js",
"typings": "lib/index.d.ts"
}
publishConfig.executableFiles
Стандартно, з міркувань переносимості, жодні файли, окрім тих, що перелічено у полі bin, не буде позначено як виконувані у результуючому архіві пакунків. Поле executableFiles
дозволяє вам оголошувати додаткові поля, які повинні мати прапорець виконуваності (+x), навіть якщо вони не доступні безпосе редньо через поле bin.
{
"publishConfig": {
"executableFiles": [
"./dist/shim.js"
]
}
}
publishConfig.directory
Ви також можете використовувати поле publishConfig.directory
для налаштування опублікованої підтеки відносно поточного package.json
.
Очікується, що у зазначеній теці міститиметься модифікована версія поточного пакунка (зазвичай за допомогою сторонніх засобів збирання).
У цьому прикладі тека
"dist"
повинна міститиpackage.json
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist"
}
}
publishConfig.linkDirectory
- Стандартно: true
- Тип: Boolean
Якщо встановлено значення true
, під час локальної розробки проєкт буде зʼєднано з текою publishConfig.directory
.
Наприклад:
{
"name": "foo",
"version": "1.0.0",
"publishConfig": {
"directory": "dist",
"linkDirectory": true
}
}
pnpm.overrides
У цьому полі ви можете вказати pnpm перевизначити будь-яку залежність у графі залежностей. Це корисно для того, щоб змусити всі ваші пакунки використовувати одну версію залежності, перенести виправлення, замінити залежність форком або видалити невикористовувану залежність.
Зверніть увагу, що поле перевизначень можна встановити лише у корені проєкту.
Приклад поля "pnpm"."overrides"
:
{
"pnpm": {
"overrides": {
"foo": "^1.0.0",
"quux": "npm:@myorg/quux@^1.0.0",
"bar@^2.1.0": "3.0.0",
"qar@1>zoo": "2"
}
}
}
Ви можете вказати пакунок, до якого належить перевизначена залежність, відокремивши селектор пакунка від селектора залежності символом ">", наприклад, qar@1>zoo
перевизначить лише залежність zoo
пакунка qar@1
, а не будь-які інші залежності.
Перевизначення можна визначити як посилання на специфікацію прямої залежності.
Це досягається шляхом додавання до імені залежності префікса $
:
{
"dependencies": {
"foo": "^1.0.0"
},
"pnpm": {
"overrides": {
"foo": "$foo"
}
}
}
Пакунок, на який посила ються, не обовʼязково повинен збігатися з пакунком, на який посилається перевизначений:
{
"dependencies": {
"foo": "^1.0.0"
},
"pnpm": {
"overrides": {
"bar": "$foo"
}
}
}
Якщо ви вважаєте, що використання певного пакунка не потребує однієї з його залежностей, ви можете вилучити її за допомогою -
. Наприклад, якщо пакунок foo@1.0.0
потребує великого пакунка з назвою bar
для функції, яку ви не використовуєте, вилучення цього пакунка може скоротити час встановлення:
{
"pnpm": {
"overrides": {
"foo@1.0.0>bar": "-"
}
}
}
Ця можливість особливо корисна для optionalDependencies
, де більшість необовʼязкових пакунків можна безпечно пропустити.
pnpm.packageExtensions
Поля packageExtensions
надають можливість розширити наявні визначення пакунків додатковою інформацією. Наприклад, якщо react-redux
повинен мати react-dom
у своїх peerDependencies
, але не має, можна виправити react-redux
за допомого ю packageExtensions
:
{
"pnpm": {
"packageExtensions": {
"react-redux": {
"peerDependencies": {
"react-dom": "*"
}
}
}
}
}
Ключами у packageExtensions
є назви пакунків або назви пакунків і діапазони semver, тому можна виправити лише деякі версії пакунків:
{
"pnpm": {
"packageExtensions": {
"react-redux@1": {
"peerDependencies": {
"react-dom": "*"
}
}
}
}
}
Наступні поля можна розширити за допомогою packageExtensions
: dependencies
, optionalDependencies
, peerDependencies
і peerDependenciesMeta
.
Більший приклад:
{
"pnpm": {
"packageExtensions": {
"express@1": {
"optionalDependencies": {
"typescript": "2"
}
},
"fork-ts-checker-webpack-plugin": {
"dependencies": {
"@babel/core": "1"
},
"peerDependencies": {
"eslint": ">= 6"
},
"peerDependenciesMeta": {
"eslint": {
"optional": true
}
}
}
}
}
}
Разом з Yarn ми підтримуємо базу даних packageExtensions
для виправлення несправних пакунків в екосистемі.
Якщо ви використовуєте packageExtensions
, подумайте про те, щоб надіслати PR і внести ваше розширення до бази даних @yarnpkg/extensions
.
pnpm.peerDependencyRules
pnpm.peerDependencyRules.ignoreMissing
pnpm не виводитиме попередження про відсутні у цьому списку прямі залежності.
Наприклад, у наступній конфігурації pnpm не виводитиме попередження, якщо залежність потребує react
, але react
не встановлено:
{
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": ["react"]
}
}
}
Також можна використовувати шаблони назв пакунків:
{
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": ["@babel/*", "@eslint/*"]
}
}
}
pnpm.peerDependencyRules.allowedVersions
Попередження про незадоволені залежності не буде виведено для залежностей із вказаного діапазону.
Наприклад, якщо у вас є залежності, які потребують react@16
, але ви знаєте, що вони чудово працюють з react@17
, то ви можете використовувати наступну конфігурацію:
{
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"react": "17"
}
}
}
}
Це скаже pnpm, що будь-яка залежність, яка має react у своїх прямих залежностях, повинна дозволити встановлення react
v17.
Також можна вимкнути попередження лише для прямих залежностей певних пакунків. Наприклад, у наведеній нижче конфігурації react
v17 буде дозволено лише тоді, коли він є в однорангових залежностях пакунка button
v2 або в залежностях будь-якого пакунка card
:
{
"pnpm": {
"peerDependencyRules": {
"allowedVersions": {
"button@2>react": "17",
"card>react": "17"
}
}
}
}
pnpm.peerDependencyRules.allowAny
allowAny
— масив шаблонів назв пакунків, будь-яка пряма залежність, що відповідає шаблону, буде розвʼязана з будь-якої версії, незалежно від діапазону, вказаного у peerDependencies
. Наприклад:
{
"pnpm": {
"peerDependencyRules": {
"allowAny": ["@babel/*", "eslint"]
}
}
}
Наведений вище параметр вимкне попередження про невідповідність версій залежностей, повʼязаних з пакунками @babel/
або eslint
.
pnpm.neverBuiltDependencies
Це поле дозволяє ігнорувати збірки певних залежностей. Скрипти "preinstall", "install" і "postinstall" перелічених пакунків не буде виконано під час встановлення.
Приклад поля "pnpm"."neverBuiltDependencies"
:
{
"pnpm": {
"neverBuiltDependencies": ["fsevents", "level"]
}
}
pnpm.onlyBuiltDependencies
Список назв пакунків, які дозволено виконувати під час встановлення. Якщо це поле наявне, лише для пакунків з цього списку можна буде запустити сценарії встановлення.
Приклад:
{
"pnpm": {
"onlyBuiltDependencies": ["fsevents"]
}
}
pnpm.onlyBuiltDependenciesFile
Цей параметр конфігурації дозволяє користувачам вказати JSON-файл зі списком лише тих пакунків, для яких дозволено запускати сценарії встановлення під час процесу встановлення pnpm. За допомогою цього ви можете підвищити безпеку або гарантувати, що під час встановлення скрипти виконуватимуться лише у певних залежностях.
Приклад:
{
"dependencies": {
"@my-org/policy": "1.0.0"
},
"pnpm": {
"onlyBuiltDependenciesFile": "node_modules/@my-org/policy/onlyBuiltDependencies.json"
}
}
Сам JSON-файл повинен містити масив імен пакунків:
[
"fsevents"
]
pnpm.allowedDeprecatedVersions
Цей параметр дозволяє вимкнути попередження про застарілість певних пакунків.
Приклад:
{
"pnpm": {
"allowedDeprecatedVersions": {
"express": "1",
"request": "*"
}
}
}
У наведеній вище конфігурації pnpm не виводитиме попередження про застарілість для будь-якої версії request
і для v1 express
.
pnpm.patchedDependencies
Це поле буде додано/оновлено автоматично під час запуску pnpm patch-commit. Це словник, де ключем має бути назва пакунка та його точна версія. Значення має бути відносним шляхом до файлу виправлення.
Приклад:
{
"pnpm": {
"patchedDependencies": {
"express@4.18.1": "patches/express@4.18.1.patch"
}
}
}
pnpm.allowNonAppliedPatches
Якщо true
, встановлення не завершиться невдачею, якщо деякі з виправлень з поля patchedDependencies
не було застосовано.
{
"pnpm": {
"patchedDependencies": {
"express@4.18.1": "patches/express@4.18.1.patch"
},
"allowNonAppliedPatches": true
}
pnpm.updateConfig
pnpm.updateConfig.ignoreDependencies
Іноді ви не можете оновити залежність. Наприклад, остання версія залежності почала використовувати ESM, але ваш проєкт ще не в ESM. На жаль, такий пакунок завжди буде виведено командою pnpm outdated
і оновлено при виконанні pnpm update --latest
. Втім, ви можете перелічити пакунки, які не потрібно оновлювати, у полі ignoreDependencies
:
{
"pnpm": {
"updateConfig": {
"ignoreDependencies": ["load-json-file"]
}
}
}
Також підтримуються шаблони, тому ви можете ігнорувати будь-які пакунки з області видимості: @babel/*
.
pnpm.auditConfig
pnpm.auditConfig.ignoreCves
Список ідентифікаторів CVE, які буде проігноровано командою pnpm audit
.
{
"pnpm": {
"auditConfig": {
"ignoreCves": [
"CVE-2022-36313"
]
}
}
}
pnpm.auditConfig.ignoreGhsas
Список кодів GHSA, які буде проігноровано командою pnpm audit
.
{
"pnpm": {
"auditConfig": {
"ignoreGhsas": [
"GHSA-42xw-2xvc-qx8m",
"GHSA-4w2v-q235-vp99",
"GHSA-cph5-m8f7-6c5x",
"GHSA-vh95-rmgr-6w4m"
]
}
}
}
pnpm.requiredScripts
Скрипти, перелічені у цьому масиві, будуть потрібні у кожному проєкті робочого простору. Інакше виконання pnpm -r run <script name>
завершиться невдачею.
{
"pnpm": {
"requiredScripts": ["build"]
}
}
pnpm.supportedArchitectures
Ви можете вказати архітектури, для яких ви хочете встановити необовʼязкові залежності, навіть якщо вони не відповідають архітектурі системи, на якій виконується встановлення.
Наприклад, у наведеній нижче конфігурації вказано встановити необовʼязкові залежності для Windows x64:
{
"pnpm": {
"supportedArchitectures": {
"os": ["win32"],
"cpu": ["x64"]
}
}
}
Тоді як ця конфігурація встановить необовʼязкові залежності для Windows, macOS та архітектури системи, на якій наразі виконується встановлення. Вона включає артефакти як для x64, так і для arm64 процесорів:
{
"pnpm": {
"supportedArchitectures": {
"os": ["win32", "darwin", "current"],
"cpu": ["x64", "arm64"]
}
}
}
Крім того, supportedArchitectures
також підтримує вказівку libc
системи.
pnpm.ignoredOptionalDependencies
Якщо необовʼязкова залежність має імʼя у цьому масиві, її буде пропущено. Наприклад:
{
"pnpm": {
"ignoredOptionalDependencies": ["fsevents", "@esbuild/*"]
}
}
pnpm.executionEnv.nodeVersion
Вказує, яку саме версію Node.js слід використовувати для виконання проєкту.
pnpm автоматично встановить вказану версію Node.js і використовуватиме її для виконання команд pnpm run
або команди pnpm node
.
Наприклад:
{
"pnpm": {
"executionEnv": {
"nodeVersion": "16.16.0"
}
}
}
resolutions
Функціонально ідентичне до pnpm.overrides
, це поле призначене для полегшення міграції з Yarn.
resolutions
та pnpm.overrides
буде обʼєднано перед резолюцією пакунків (при цьому pnpm.overrides
матиме пріоритет), що може бути корисним, якщо ви мігруєте з Yarn і вам потрібно налаштувати кілька пакунків лише під pnpm.