pnpm каталоги + монорепозиторій

Одна з проблем, коли у вас фронтова монорепа — це контроль і управління версіями бібліотек. Саме з цією задачею ми зіткнулися на одному з наших проєктів.

pic

Як я себе відчуваю, коли розумію, що буду оновлювати версії бібліотеки…

Трохи технічних деталей про проєкт

  • монорепозиторій з оркестратором nx.
    Тип монорепи — Package-Based Repository;
  • пакетний менеджер pnpm разом із функціональністю pnpm workspaces;
  • структура стандартна: /apps - містить усі застосунки, /packages - усі пакети;
  • усі застосунки на Nuxt 3;
  • усі пакети на vue 3 або чистому typescript, білдимо все на vite;
  • на поточний момент маємо 4 — застосунки, 22 — пакети;
  • усі залежності пакетів екстерналізуються (externalize).
    Якщо спростити, то у ваш білд не потрапляють бібліотеки з node_modules, вони там будуть підключені через import або require; (згадаю тут лібку vite-plugin-externalize-deps 👌)

А яка власне проблема?

Для прикладу, хочемо підняти версію Nuxt.

Для цього ми змінюємо її у всіх застосунках і деяких пакетах, які є nuxt модулями. Це оновлення тягне за собою оновлення версій деяких залежних бібліотек. І ось ви ходите по кожному застосунку і пакету, і перевіряєте чи все ок і при потребі піднімаєте версію.

Чи це дуже важка робота? — точно ні.

Чи це монотонна робота і є шанс десь помилитись? — точно так!

Ця проблема існує вже не перший рік і варіантів багато:

  • якась автоматизація.
    Скрипт, який пройде по всій системі і підніме версію;
  • ще автоматизація у вигляді різних ботів;
  • кореневий package.json, або подібні до цього приколи;
  • деякі з оркестраторів, беруть це на себе, якщо не помиляюсь rush якраз полегшив процес оновлення;

І всі ці варіанти — ок, якщо вони вирішують вашу проблему, але мене завжди не покидало відчуття, що це якийсь костиль і зайве ускладнення.

І саме тут на допомогу приходить pnpm catalogs.

PNPM Catalogs

Ідея дуже проста — давайте зберігати версії залежностей в одному місці, а в свою чергу усі package.json-и будуть посилатись на це місце.

Виглядає це наступним чином:

pnpm-workspace.yaml

packages:  
 - packages/*  
 - apps/*  
# тут наші каталоги з ім'ям  
catalogs:  
 # ми іменуємо по певному логічному доменному імені  
 domain1:  
 nuxt: 3.13.2  
 vue: 3.5.12  
 domain2:  
 nuxt: 3.13.1  
 vue: 3.5.12  
# дефолтний каталог без імені  
catalog:  
 nuxt: 3.12.5  
 vue: 3.4.1

package.json, якогось з пакетів чи застосунка

 // посилаємось на версію з каталогу domain1  
{  
 "name": "package1",  
 "dependencies": {  
 "vue": "catalog:domain1"  
 }  
}  
// посилаємось на версії з каталогу domain2  
{  
 "name": "package2",  
 "dependencies": {  
 "vue": "catalog:domain2",  
 "nuxt": "catalog:domain2"  
 }  
}  
// посилаємось на версії з дефолтного каталогу  
{  
 "name": "package3",  
 "dependencies": {  
 "vue": "catalog:",  
 "nuxt": "catalog:",  
 }  
}

Тепер, щоб оновити версію:

  • ідемо в pnpm-workspace.yaml;
  • змінюємо версію;
  • запускаємо pnpm i;

Це не звільняє нас від необхідності перевірити чи всі версії коректно стали і не конфліктують одна з одною, але як мінімум частину рутини і ризик помилки ми знизили.

Що ще?

  • щоб швидко переїхати на каталоги, запускаємо команду pnpx codemod pnpm/catalog;
  • маємо в планах подивитись і покрутити taze від Anthone Fu;
  • враження від pnpm catalogs — все просто, вирішує нашу проблему і ми задоволені;

Перекладено з: pnpm catalogs + монорепозиторій

Leave a Reply

Your email address will not be published. Required fields are marked *