
In den letzten Jahren hat sich das Konzept der
Mono-Repositories erfolgreich etabliert, da es den Prozess der Entwicklung modularer Softwareprojekte wie mikroservicebasierter Infrastrukturen erheblich vereinfachen kann. Die Hauptvorteile dieses architektonischen Ansatzes liegen in der Praxis auf der Hand. Daher schlage ich vor, ein eigenes Test-
Mono-Repository von Grund auf neu zu erstellen und gleichzeitig die Nuancen der Arbeit mit
Garnarbeitsbereichen und
Herna zu verstehen . Nun, fangen wir an!
Betrachten Sie die Struktur unseres Projekts, bei der es sich um drei Bibliotheken im Ordner
packages / sowie in
package.json im Stammverzeichnis handelt.
âââ package.json âââ packages âââ app â âââ index.js â âââ package.json âââ first â âââ index.js â âââ package.json âââ second âââ index.js âââ package.json
Es versteht sich, dass wir zuerst zwei und zwei unabhÀngige Bibliotheken sowie eine
App- Bibliothek haben, die Funktionen aus den ersten beiden importiert. Der Einfachheit halber werden alle drei Pakete im
Paketverzeichnis abgelegt. Sie können sie im Stammordner belassen oder in einem Verzeichnis mit einem anderen Namen ablegen. Um jedoch den allgemein anerkannten Konventionen zu folgen, werden sie auf diese Weise abgelegt.
Die Bibliotheken
1 und
2 enthalten zur Vereinfachung des Experiments nur eine Funktion in
index.js , von denen jede im Namen des Moduls eine Hallo-Zeichenfolge
zurĂŒckgibt . FĂŒr das
erste Beispiel sieht es so aus:
Im
App- Modul zeigen wir die Meldung
Hallo von der App in der Konsole sowie GrĂŒĂe von zwei anderen Paketen an:
Damit
erstens und
zweitens in der
App verfĂŒgbar sind , bezeichnen wir sie als AbhĂ€ngigkeiten in
AbhÀngigkeiten .
FĂŒgen Sie auĂerdem fĂŒr jede Bibliothek das PrĂ€fix
@ monorepo / im Wert von
name zum Paketnamen vor dem
Hauptpaketnamen in der lokalen
package.json hinzu .
Warum brauche ich ein PrĂ€fix mit einem Hundesymbol vor dem Paketnamen npm (@ monorepo /)?Das HinzufĂŒgen eines PrĂ€fixes ist optional, aber dies
ist genau
die Konvention der Paketbenennung, an die sich viele Monorepositorys halten:
babel ,
Material UI ,
eckig und andere. Tatsache ist, dass jeder Benutzer oder jede Organisation seinen eigenen
Bereich auf der
npm- Website hat.
Daher besteht die Garantie, dass alle Module mit dem
@ somescope / postfix vom
somescope- Team und nicht von Angreifern erstellt werden. DarĂŒber hinaus können bereits vergebene Modulnamen aufgerufen werden. Sie können beispielsweise nicht einfach Ihr eigenes
Utils- Modul erstellen, da eine solche Bibliothek
bereits vorhanden ist .
Wenn Sie jedoch das Postfix
@ myscopename / hinzufĂŒgen , können Sie unsere Utils (
@ myscopename / utils ) mit Blackjack und jungen Damen erhalten.
Ein Analogon aus dem wirklichen Leben fĂŒr unser Testprojekt können verschiedene Bibliotheken fĂŒr die Arbeit mit Daten, Validierungswerkzeugen, Analysen oder nur eine Reihe von UI-Komponenten sein. Wenn wir davon ausgehen, dass wir eine
Web- und eine
mobile Anwendung entwickeln werden (z. B. mit
React bzw.
React Native ) und einen Teil der wiederverwendeten Logik haben, kann es sich lohnen, sie fĂŒr die spĂ€tere Verwendung in anderen Projekten in separate Komponenten zu integrieren. FĂŒgen Sie dazu den Server auf
Node.js hinzu und Sie erhalten einen sehr realen Fall aus dem Leben.
Garnarbeitsbereiche
Der letzte Schliff vor dem Erstellen eines vollwertigen
Mono-Repositorys ist das Design von
package.json im Stammverzeichnis unseres Repositorys. Beachten Sie die Eigenschaft
workspaces - wir haben den Wert von
packages / * angegeben , was "alle UnterschlĂŒssel im Paketordner" bedeutet. In unserem Fall ist dies die
erste und
zweite App .
AuĂerdem muss in
package.json "private": true angegeben
werden , da
Arbeitsbereiche nur in privaten Projekten verfĂŒgbar sind.
FĂŒhren Sie den Befehl
yarn (analog zu
yarn install oder
npm install ) aus dem Stammverzeichnis aus, damit alles abheben kann. Da die im
App- Modul vorhandenen AbhÀngigkeiten im
Stammpaket.json als
Arbeitsbereiche definiert sind, werden wir nichts von der
npm-Registrierung herunterladen, sondern einfach unsere Pakete binden ("verlinken").
yarn

Jetzt können wir den
Knotenbefehl ausfĂŒhren
. aus dem Stammverzeichnis, in dem das Skript aus der
Datei packages / app / index.js ausgefĂŒhrt wird .
node .

Mal sehen, wie es funktioniert.
Durch Aufrufen von
Garn haben wir in
node_modules symbolische Links zu unseren Verzeichnissen im
Paketordner erstellt .

Aufgrund dieser AbhĂ€ngigkeitsbeziehung haben wir einen groĂen Vorteil: Wenn wir jetzt das
erste und
zweite Modul Àndern, erhÀlt unsere
App die aktuelle Version dieser Pakete, ohne sie neu zu erstellen. In der Praxis ist es sehr praktisch, weil Wir können Pakete lokal entwickeln und sie dennoch als AbhĂ€ngigkeiten von Drittanbietern definieren (zu denen sie schlieĂlich werden).
Der nÀchste wichtige Vorteil, den Sie durch die Arbeit mit
Garnarbeitsbereichen erzielen können, ist die Organisation der Speicherung von AbhÀngigkeiten von Drittanbietern.
Weitere Informationen zum Speichern von AbhÀngigkeiten auf oberster Ebene.Angenommen, wir wollten die
Lodash- Bibliothek in der
ersten und
zweiten verwenden .
Durch AusfĂŒhren des Befehls yarn add lodash aus den entsprechenden Verzeichnissen erhalten wir eine Aktualisierung der lokalen
package.json - die aktuelle Version des Pakets wird in
AbhÀngigkeiten angezeigt .
"dependencies": { "lodash": "^4.17.11" }
Was das
lodash- Paket
selbst betrifft - physisch wird die Bibliothek einmal in
node_modules auf der Stammebene installiert.
Wenn die erforderliche Version des externen Pakets (in unserem Fall
lodash ) fĂŒr
first und second unterschiedlich ist (z. B. benötigen
Sie zuerst lodash v3.0.0 und in
second v4.0.0 ),
gelangt ein Paket mit einer niedrigeren Version (
3.0.0 ) zu den root
node_modules , und die
lodash- Version fĂŒr das
zweite Modul wird in den lokalen
Paketen / second / node_modules gespeichert .
ZusĂ€tzlich zu den Vorteilen kann dieser Ansatz geringfĂŒgige Nachteile aufweisen, die das
Garn mit Hilfe zusÀtzlicher Fahnen umgehen kann. Weitere Informationen zu solchen Nuancen finden Sie in der
offiziellen Dokumentation .
Lerna hinzufĂŒgen
Der erste Schritt bei der Arbeit mit
lerna ist die Installation des Pakets. Normalerweise fĂŒhren sie eine globale Installation durch (
Garn global add lerna oder
npm i -g lerna ). Wenn Sie jedoch nicht sicher sind, ob Sie diese Bibliothek verwenden möchten, können Sie den Aufruf mit
npx verwenden .
Wir werden
lerna aus dem Stammverzeichnis initialisieren:
lerna init

TatsĂ€chlich haben wir mit Hilfe eines Befehls mehrere Aktionen gleichzeitig ausgefĂŒhrt: ein Git-Repository erstellt (falls es zuvor nicht initialisiert worden war), eine
lerna.json- Datei erstellt und unser
Stammpaket.json aktualisiert.
FĂŒgen Sie nun in der neu erstellten Datei
lerna.json zwei Zeilen hinzu -
"npmClient": "Garn" und
"useWorkspaces": true . In der letzten Zeile steht, dass wir bereits
Garnarbeitsbereiche verwenden und der Ordner app / node_modules mit symbolischen Links zum
ersten und
zweiten nicht erstellt werden muss .
Tests mit Lerna
Um die Bequemlichkeit der Arbeit mit
lerna zu
demonstrieren, fĂŒgen Sie Tests fĂŒr unsere Bibliotheken hinzu.
Aus dem Stammverzeichnis installieren wir das Paket zum Testen -
Scherz . FĂŒhren Sie den folgenden Befehl aus:
yarn add -DW jest
Warum brauche ich das Flag -DW?Das Flag -D (- dev) wird benötigt, damit das Scherzpaket als Dev-AbhÀngigkeit installiert wird, und das Flag -W (- ignore-workspace-root-check) ermöglicht die Installation auf der Root-Ebene (die wir benötigen).
Der nĂ€chste Schritt ist das HinzufĂŒgen einer Testdatei zu unserem Paket. Zur Vereinfachung unseres Beispiels werden wir alle Tests Ă€hnlich machen. Im
ersten Beispiel sieht die Testdatei folgendermaĂen aus:
Wir mĂŒssen auch ein Skript hinzufĂŒgen, um Tests in
package.json jeder unserer Bibliotheken
auszufĂŒhren :
Der letzte Schliff wird die Aktualisierung der root
package.json sein . FĂŒgen Sie ein
Testskript hinzu , das
lerna run test --stream aufruft . Der Parameter nach
lerna run definiert den Befehl, der in jedem unserer Pakete aus dem
Paket / Ordner
aufgerufen wird, und das Flag
--stream ermöglicht es uns, die Ausgabe der Ergebnisse im Terminal
anzuzeigen .
Infolgedessen
sieht package.json aus dem Stammverzeichnis
folgendermaĂen aus:
Um die Tests auszufĂŒhren, mĂŒssen wir nur den Befehl vom Stammverzeichnis unseres Projekts aus ausfĂŒhren:
yarn test

Versions-Upgrade mit Lerna
Die nÀchste beliebte Aufgabe, mit der
lerna die QualitÀt bewÀltigen kann, ist die Aktualisierung der Paketversionen. Stellen Sie sich vor, wir haben uns nach der Implementierung der Tests entschlossen, unsere Bibliotheken von 1.0.0 auf 2.0.0 zu aktualisieren.
FĂŒgen Sie dazu einfach die Zeile
"update: version": "lerna version --no-push" in das
Skriptfeld der
Datei " root
package.json" ein und fĂŒhren Sie dann "
Garn update: version" aus dem Stammverzeichnis aus. Das Flag
--no-push wird hinzugefĂŒgt, damit die Ănderungen nach dem Aktualisieren der Version nicht an das Remote-Repository gesendet werden, was
lerna standardmĂ€Ăig tut (ohne dieses Flag).
Infolgedessen
sieht unser root
package.json folgendermaĂen aus:
FĂŒhren Sie das Versionsaktualisierungsskript aus:
yarn update:version
Als nÀchstes werden wir aufgefordert, die Version auszuwÀhlen, zu der wir wechseln möchten:

Durch Klicken auf die
Eingabetaste erhalten wir eine Liste der Pakete, in denen die Version aktualisiert wird.

Wir bestÀtigen das Update durch Eingabe von
y und erhalten eine Nachricht ĂŒber das erfolgreiche Update.

Wenn wir versuchen, den Befehl
git status auszufĂŒhren, erhalten wir die Nachricht, dass
nichts festgeschrieben werden muss Die lerna-Version aktualisiert nicht nur die Paketversionen, sondern erstellt auch ein Git-Commit und ein Tag, das die neue Version angibt (in unserem Fall v2.0.0).
Funktionen der Arbeit mit dem lerna version teamWenn Sie im
Skriptfeld der
Datei root
package.json die Zeile
"version": "lerna version --no-push" anstelle von
"update: version": "lerna version --no-push" hinzufĂŒgen , können Sie höchstwahrscheinlich auf unerwartetes Verhalten stoĂen rote Konsole. Tatsache ist, dass
npm-scripts standardmĂ€Ăig den
Versionsbefehl (reserviertes Skript) unmittelbar nach dem Aktualisieren der Paketversion
aufruft , was zu einem rekursiven Aufruf der
lerna-Version fĂŒhrt . Um diese Situation zu vermeiden, reicht es aus, dem Skript einen anderen Namen zu geben, z. B.
update: version , wie in unserem Beispiel.
Fazit
Diese Beispiele zeigen ein Hundertstel aller Möglichkeiten, die
lerna in Verbindung mit
Garnarbeitsbereichen bietet. Leider habe ich bisher keine detaillierten Anweisungen fĂŒr die Arbeit mit Monorepositories auf Russisch gefunden, sodass wir davon ausgehen können, dass der Anfang gemacht wurde!
Link zum Testprojekt-Repository.