javascript - Partajarea unei biblioteci typescript într-un monorepo


Încerc să configurez un monorepo cu 3 servicii care împart codul unei biblioteci.

Aceasta este situația actuală:

repo: web
pdf/
  package.json
    reference to shared-ts using github url
  tsconfig.json
frontend/
  package.json
    reference to shared-ts using github url
  tsconfig.json
repo: mobile (react-native)
  package.json
    reference to shared-ts using github url
  tsconfig.json
repo: shared-ts
  package.json
  tsconfig.json

Funcționează, dar e o bătaie de cap să faci commit în shared-ts, să construiești, să schimbi hash-ul în package.json și să faci din nou commit.

Acesta este ceea ce aș dori să realizez:

repo: monorepo
pdf/
  package.json
    reference to ../shared-ts
  tsconfig.json
frontend/
  package.json
    reference to ../shared-ts
  tsconfig.json
mobile/
  package.json
    reference to ../shared-ts
  tsconfig.json
shared-ts/
  package.json
  tsconfig.json

Până acum am încercat:

  • Referințe la proiecte TypeScript, dar se pare că nu există nicio modalitate de a avea dependențe în proiectul shared-ts
  • "shared-ts": "../shared-ts" în package.json, dar copiază shared-ts în node_modules-ul fiecărui pachet, așa că trebuie să rulez din nou yarn de fiecare dată când fac o modificare
  • yarn link în postinstall: eroare TS2307: Nu se poate găsi modulul 'shared-ts' sau declarațiile sale de tip corespunzătoare.
  • crearea unui symlink direct în postinstall cu ln -s ../shared-ts/ node_modules/shared-ts/, dar se pare că TypeScript nu reușește să găsească modulul
  • npm link în postinstall pare cea mai promițătoare opțiune, dar este foarte lent și am probleme să-l rulez în CI din cauza unor probleme de permisiuni.

Există o modalitate bună de a face asta? Ai vreo idee despre alte lucruri pe care le-aș putea încerca?

Răspuns #1

Cazul tău de utilizare poate fi gestionat folosind workspaces npm7. Pe scurt, noua structură a monorepo-ului tău ar trebui să arate ca mai jos:

repo: monorepo
package.json // <- here you define the workspaces
pdf/
  package.json
    reference to shared-ts
  tsconfig.json
frontend/
  package.json
    reference to shared-ts
  tsconfig.json
mobile/
  package.json
    reference to shared-ts
  tsconfig.json
shared-ts/
  package.json
  tsconfig.json

Trebuie să listați spațiile de lucru în fișierul rădăcină package.json, care ar putea arăta aproximativ astfel:

{
  "name": "awesome-monorepo",
  "workspaces": [
    "pdf",
    "frontend",
    "mobile",
    "shared-ts"
  ]
}

După ce faci asta, oriunde în monorepo alegi să folosești shared-ts poți să adaugi asta la dependencies sau devDependencies pur și simplu referindu-te la numărul versiunii în loc de calea relativă.

Toate modulele node, inclusiv spațiile de lucru, sunt mutate la rădăcina node_modules, motiv pentru care rezolvarea modulelor ar trebui să funcționeze fără probleme.

Răspunsul #2

Soluția 1:

cu Lerna

poți folosi workspace și Lerna

yarn workspace & lerna
├── README.md
├── lerna.json
├── package.json
├── packages
│   ├── pdf
│   │   ├── package.json   /*  "shared-ts": "^1.0.0" */
│   │   └──  src
│   ├── frontend
│   │   ├── package.json
│   │   └── src
│   ├── mobile
│   │   ├── package.json
│   │   └── src
│   ├── shared-ts
│   │   ├── package.json
│   │   └──  src
├── tsconfig.json
└── yarn.lock

aici este un exemplu de depozit

aici poți vedea că x-cli folosește x-core partajat

Soluția 2:

fără Lerna

poți folosi pachetul mtsl care ne permite să facem legături simbolice tangibile. poți instala acest pachet la nivel global

npm install -g mtsl

atunci trebuie doar să începi să separi aceste trei comenzi în terminal.

mtsl startwithoutadd -s path_of_project/packages/shared-ts -d path_of_project/packages/pdf/node_modules/shared-ts

mtsl startwithoutadd -s path_of_project/packages/shared-ts -d path_of_project/packages/frontend/node_modules/shared-ts

mtsl startwithoutadd -s path_of_project/packages/shared-ts -d path_of_project/packages/mobile/node_modules/shared-ts

Notă nu opriți acești trei observatori. După testare, puteți crea o singură comandă din scriptul package.json