Робочий простір
pnpm має вбудовану підтримку монорепозиторіїв (також відомих як репозиторії з декількома пакунками, репозиторії з декількома проєктами або монолітні репозиторії). Ви можете створити робочий простір, щоб обʼєднати кілька проєктів в одному репозиторії.
Робоча область повинна мати файл pnpm-workspace.yaml у корені.
Якщо ви розглядаєте управління монорепозиторіями, ви також можете розглянути Bit.
Bit використовує pnpm під капотом, але автоматизує багато речей, які зараз виконуються вручну в традиційному робочому просторі, керованому pnpm/npm/Yarn. Є стаття про bit install, яка розповідає про це: Безболісне керування залежностями Monorepo за допомогою Bit.
Протокол робочого простору (workspace:)
Якщо linkWorkspacePackages встановлено у true, pnpm буде лінкувати пакунки з робочого простору, якщо доступні пакунки відповідають оголошеним діапазонам. Наприклад, foo@1.0.0 повʼязано з bar, якщо bar має "foo": "^1.0.0" у своїх залежностях і foo@1.0.0 знаходиться у робочому просторі. Однак, якщо bar має "foo": "2.0.0" у залежностях і foo@2.0.0 відсутній у робочому просторі, foo@2.0.0 буде встановлено з реєстру. Така поведінка вносить певну невизначеність.
На щастя, pnpm підтримує протокол workspace:. При використанні цього протоколу pnpm відмовлятиметься виконувати перетворення на будь-що, окрім пакунків локального робочого простору. Отже, якщо ви задасте "foo": "workspace:2.0.0", цього разу встановлення не вдасться, оскільки "foo@2.0.0" у робочому просторі відсутній.
Цей протокол особливо корисний, коли параметр linkWorkspacePackages має значення false. У цьому випадку pnpm буде компонувати пакунки з робочого простору лише за умови використання протоколу workspace:.
Посилання на пакунки робочого простору через псевдоніми
Припустимо, у робочому просторі у вас є пакунок з назвою foo. Зазвичай, ви посилаєтесь на нього як "foo": "workspace:*".
Якщо ви хочете використовувати інший псевдонім, наступний синтаксис також буде працювати: "bar": "workspace:foo@*".
Перед публікацією псевдоніми перетворюються на звичайні залежності від псевдонімів. Вищенаведений приклад стане: "bar": "npm:foo@1.0.0".
Посилання на пакунки робочого простору через їхній відносний шлях
У робочому просторі з 2 пакунками:
+ packages
+ foo
+ bar
bar може мати foo у своїх залежностях, оголошених як "foo": "workspace:../foo". Перед публікацією ці специфікації перетворюються у звичайні специфікації версій, які підтримуються усіма менеджерами пакунків.
Публікація пакунків робочого простору
Коли пакунок робочого простору запаковано до архіву (за допомогою pnpm pack або однієї з команд публікації, наприклад pnpm publish), ми динамічно замінюємо будь-яку залежність workspace: на:
- The corresponding version in the target workspace (if you use
workspace:,workspace:*,workspace:~, orworkspace:^) - Асоційований діапазон Semver (для будь-якого іншого типу діапазону)
A bare workspace: without a version range is treated as workspace:*.
Наприклад, якщо у робочому просторі є foo, bar, qar, zoo і всі вони мають версію 1.5.0, то наступне:
{
"dependencies": {
"foo": "workspace:*",
"bar": "workspace:~",
"qar": "workspace:^",
"zoo": "workspace:^1.5.0"
}
}
Буде перетворено на:
{
"dependencies": {
"foo": "1.5.0",
"bar": "~1.5.0",
"qar": "^1.5.0",
"zoo": "^1.5.0"
}
}
Ця функція дозволяє вам покладатися на ваші локальні пакунки робочих просторів і водночас публікувати отримані пакунки у віддаленому реєстрі без проміжних кроків публікації — ваші користувачі зможуть використовувати ваші опубліковані робочі простори як будь-які інші пакунки, отримуючи вигоду від гарантій, що їх пропонує Semver.
Процес релізу
Керування версіями пакунків у робочому просторі є складним завданням, і наразі pnpm не надає вбудованого рішення для цього. Однак є 2 добре протестовані інструменти, які працюють з версіями і підтримують pnpm:
Щоб дізнатися, як налаштувати сховище за допомогою Rush, прочитайте цю сторінку.
Про використання Changesets з pnpm читайте в цьому посібнику.
Усунення несправностей
pnpm не може гарантувати виконання скриптів у топологічному порядку, якщо між залежностями робочого простору є цикли. Якщо pnpm виявить циклічні залежності під час встановлення, він видасть попередження. Якщо pnpm зможе зʼясувати, які залежності спричиняють цикли, він також покаже їх.
Якщо ви бачите повідомлення Існують циклічні залежності робочого простору (There are cyclic workspace dependencies), перевірте залежності робочого простору, оголошені у dependencies, optionDependencies та devDependencies.
Приклад використання
Ось декілька найпопулярніших відкритих проєктів, які використовують функцію робочого простору pnpm:
Налаштування
linkWorkspacePackages
- Стандартно: false
- Тип: true, false, deep
Якщо цей параметр увімкнено, локально доступні пакунки буде повʼязано з node_modules замість того, щоб завантажувати їх з реєстру. Це дуже зручно в монорепо. Якщо вам потрібно, щоб локальні пакунки також були повʼязані з вкладеними залежностями, ви можете скористатися параметром deep.
В іншому випадку пакунки завантажуються і встановлюються з реєстру. Втім, пакунки робочих просторів все ще можна звʼязати за допомогою протоколу workspace:.
Пакунки звʼязуються, лише якщо їхні версії задовольняють діапазони залежностей.
injectWorkspacePackages
- Стандартно: false
- Тип: Boolean
Вмикає жорстке звʼязування всіх локальних залежностей робочого простору замість їхнього звʼязування у вигляді символічних посилань. Крім того, цього можна досягти за допомогою dependenciesMeta[].injected, що дозволяє вибірково вмикати жорстке зв’язування для певних залежностей.
Навіть якщо цей параметр увімкнено, pnpm надаватиме перевагу дедуплікації введених залежностей за допомогою символічних посилань — якщо тільки не потрібно створювати декілька графів залежностей через невідповідність однорангових залежностей. Ця поведінка контролюється параметром dedupeInjectedDeps.
dedupeInjectedDeps
- Стандартно: true
- Тип: Boolean
Якщо цей параметр увімкнено, залежності, які інжектуються, буде звʼязано з робочим простором, коли це можливо. Якщо залежний проєкт та інʼєктована залежність посилаються на ті самі однорангові залежності, то нема потреби фізично копіювати інжектовану залежність у node_modules залежного проєкту; достатньо символічного посилання.
syncInjectedDepsAfterScripts
Додано у: v10.5.0
- Стандартно: undefined
- Тип: String[]
Інʼєкції залежності робочого простору — це колекції жорстких посилань, які не додають і не видаляють файли при зміні їхніх джерел. Це спричиняє проблеми у пакунках, які потрібно зібрати (наприклад, у проєктах на TypeScript).
Цей параметр являє собою список назв скриптів. Коли будь-який з цих скриптів виконується у пакунку робочої області, інʼєкції залежностей всередині node_modules також буде синхронізовано.
preferWorkspacePackages
- Стандартно: false
- Тип: Boolean
Якщо цей параметр увімкнено, локальним пакункам з робочого простору надається перевага перед пакунками з реєстру, навіть якщо у реєстрі є новіша версія пакунка.
Цей параметр корисний лише у тому випадку, якщо у робочому просторі не використовується saveWorkspaceProtocol .
sharedWorkspaceLockfile
- Стандартно: true
- Тип: Boolean
Якщо цей параметр увімкнено, pnpm створить єдиний файл pnpm-lock.yaml у корені робочого простору. Це також означає, що всі залежності пакунків робочої області будуть знаходитися у єдиній теці node_modules (і будуть привʼязані до теки їх пакунків node_modules для розпізнавання модулів Node).
Переваги цього параметра:
- кожна залежність є одиночною
- швидші установки в монорепо
- менше змін у перевірках коду, оскільки всі вони містяться в одному файлі
Попри те, що всі залежності будуть жорстко повʼязані з кореневим node_modules, пакунки матимуть доступ лише до тих залежностей, які оголошено у їхньому package.json, таким чином строгість pnpm зберігається.
Це результат вищезгаданого символічного звʼязування.
saveWorkspaceProtocol
- Стандартно: rolling
- Тип: true, false, rolling
Цей параметр керує тим, як залежності, приєднані з робочої області, додаються до package.json.
Якщо foo@1.0.0 знаходиться у робочому просторі і ви виконуєте pnpm add foo в іншому проєкті робочого простору, нижче показано, як foo буде додано до поля залежностей. Параметр savePrefix також впливає на те, як створюється специфікація.
| saveWorkspaceProtocol | savePrefix | spec |
|---|---|---|
| false | '' | 1.0.0 |
| false | '~' | ~1.0.0 |
| false | '^' | ^1.0.0 |
| true | '' | workspace:1.0.0 |
| true | '~' | workspace:~1.0.0 |
| true | '^' | workspace:^1.0.0 |
| rolling | '' | workspace:* |
| rolling | '~' | workspace:~ |
| rolling | '^' | workspace:^ |
includeWorkspaceRoot
- Стандартно: false
- Тип: Boolean
При рекурсивному виконанні команд у робочій області, виконуйте їх також у кореневому проєкті робочої області.
ignoreWorkspaceCycles
- Стандартно: false
- Тип: Boolean
Якщо встановлено значення true, попередження про цикли робочої області не буде виведено.
disallowWorkspaceCycles
- Стандартно: false
- Тип: Boolean
Якщо встановлено значення true, встановлення не вдасться, якщо у робочій області є цикли.
failIfNoMatch
- Стандартно: false
- Тип: Boolean
Якщо встановлено значення true, CLI завершить роботу з ненульовим кодом, якщо жоден пакунок не відповідає наданим фільтрам.
Наприклад, наступна команда завершиться з ненульовим кодом, оскільки bad-pkg-name відсутній у робочій області:
pnpm --filter=bad-pkg-name test