Yarn: Arbeitsbereiche: Datei pro Arbeitsbereich sperren

Erstellt am 28. Feb. 2018  ·  54Kommentare  ·  Quelle: yarnpkg/yarn

Möchten Sie eine Funktion anfordern oder einen Fehler melden?
Besonderheit

Wie ist das aktuelle Verhalten?
Die Verwendung von Garn-Workspaces für ein Monorepo, das ein Knotenmodul der obersten Ebene enthält, erzeugt nur ein einzelnes yarn.lock am Stamm des Monorepos, ohne yarn.lock , das für das Knotenmodul der obersten Ebene spezifisch ist.

Was ist das erwartete Verhalten?
Ich möchte Garn-Arbeitsbereiche verwenden, um ein Monorepo zu verwalten, das sowohl Apps (Knotenmodule der obersten Ebene) als auch Bibliotheken enthält. Aber wenn ich nur eine einzige yarn.lock Datei im Stammverzeichnis des Monorepos habe, kann ich meine App beispielsweise nicht in ein Docker-Image packen. Ich würde gerne eine yarn.lock Datei für ausgewählte Arbeitsbereiche erhalten, die einen eigenen haben müssen, da dieser Arbeitsbereich später außerhalb des Monorepo verwendet werden kann.

Ein Beispiel:
Wenn ich ein Monorepo mit 2 Arbeitsbereichen habe: workspace-a und workspace-b . workspace-a verwendet einige der exportierten Module aus workspace-b . Wenn ich workspace-a in ein Docker-Image packen möchte (oder auf andere Weise diesen Arbeitsbereich ohne das gesamte Monorepo verpacken möchte), habe ich kein yarn.lock dafür. Das heißt, wenn ich die Dateien von workspace-a in eine andere Umgebung als das Monorepo verschiebe, fehlt mir eine yarn.lock Datei und beim Installieren von Abhängigkeiten verliere ich alle Vorteile einer Sperrdatei (in dem Wissen, dass ich die gleichen Abhängigkeiten installiere, die in der Entwicklung verwendet werden).

Ich bin ziemlich überrascht, dass ich diesbezüglich kein Problem finden konnte. Bin ich der einzige, der so mit Monorepos arbeiten möchte? Vielleicht übersehe ich etwas? Meine aktuelle Problemumgehung ist die Verwendung von lerna ohne das Hochziehen, also habe ich eine Sperrdatei pro Paket.
Das kürzlich veröffentlichte Feature nohoist scheint auch nicht zu helfen (obwohl ich gehofft habe), da es keine anderen yarn.lock pro Arbeitsbereich erstellt.
Dieses Problem hat etwas mit diesem Kommentar zu einem anderen Thema zu tun. Dachte, dass es eine eigene Ausgabe verdienen könnte.

Bitte geben Sie Ihre node.js-, Garn- und Betriebssystemversion an.
Knoten 8.9.3, Garn 1.5.1, OSX 10.13.3

cat-feature triaged

Hilfreichster Kommentar

Für uns möchten wir also nicht das gesamte Monorepo in den resultierenden Docker-Container verpacken. Wir verwenden Docker in der Produktion und diese Bilder sollten so hell wie möglich sein. Unser Mono-Repo ist ziemlich groß und enthält mehrere Microservices, die Code mithilfe von Bibliothekspaketen teilen (und einige der Bibliotheken sind für einige der Microservices relevant, aber nicht für alle). Wenn wir also einen Microservice verpacken, möchten wir, dass das Image die Dateien dieses Microservices und alle anderen Abhängigkeiten als richtige Abhängigkeiten enthält – aus unserer privaten Registrierung heruntergeladen und für den Bogen des Docker-Images erstellt.

Daher denke ich, dass die Hauptüberlegung hier darin besteht, unsere Docker-Images so leicht wie möglich zu halten, und die Verpackung des gesamten Monorepos entspricht nicht unseren Anforderungen. Auch wenn wir "yarn" im Image des Microservice ausführen, möchten wir dort keine Symlinks haben, sondern nur eine normale Abhängigkeit.

Die Lösung hier muss nicht das Erstellen einer Garn.lock-Datei pro Arbeitsbereich sein, es könnte auch ein Garnbefehl sein, der beim Packen eines bestimmten Arbeitsbereichs hilft, eine Garn.lock-Datei für einen Arbeitsbereich bei Bedarf generieren usw. ..

Hoffe, es hat geholfen, den Anwendungsfall zu klären.. 🍻

Alle 54 Kommentare

basierend auf Garn Blog :

Wenn Sie ein Paket veröffentlichen, das eine Garn.lock enthält, ist kein Benutzer dieser Bibliothek davon betroffen. Wenn Sie Abhängigkeiten in Ihrer Anwendung oder Bibliothek installieren, wird nur Ihre eigene Garn.lock-Datei berücksichtigt. Lockfiles innerhalb Ihrer Abhängigkeiten werden ignoriert.

es scheint nicht notwendig zu sein, beim Veröffentlichen des einzelnen Pakets Garn.lock zu bündeln ... es ist eher ein Entwicklungsartefakt für das gesamte Repository, daher muss es nicht in jedes Paket eingefügt werden.

@connectdotz Es wird möglicherweise nicht für eine Bibliothek oder ein veröffentlichtes Paket benötigt, aber zum

sicher... aber würde der Docker-Container der Entwicklung nicht einfach das ganze Repo und damit auch das Garn.lock haben? Ich kann sehen, dass wir Docker-Container verwenden, um unser Monorepo-Projekt für verschiedene Betriebssysteme oder Plattformen zu testen. In diesem Fall stellen wir einfach das gesamte Repo und seine Garn.lock bereit. Können Sie mir ein Beispiel für einen Anwendungsfall nennen, bei dem Sie während des Entwicklungszyklus einzelne Pakete aus dem Monorepo-Projekt in Docker-Container bereitstellen müssen, damit ich ein konkreteres Verständnis bekomme ...

Für uns möchten wir also nicht das gesamte Monorepo in den resultierenden Docker-Container verpacken. Wir verwenden Docker in der Produktion und diese Bilder sollten so hell wie möglich sein. Unser Mono-Repo ist ziemlich groß und enthält mehrere Microservices, die Code mithilfe von Bibliothekspaketen teilen (und einige der Bibliotheken sind für einige der Microservices relevant, aber nicht für alle). Wenn wir also einen Microservice verpacken, möchten wir, dass das Image die Dateien dieses Microservices und alle anderen Abhängigkeiten als richtige Abhängigkeiten enthält – aus unserer privaten Registrierung heruntergeladen und für den Bogen des Docker-Images erstellt.

Daher denke ich, dass die Hauptüberlegung hier darin besteht, unsere Docker-Images so leicht wie möglich zu halten, und die Verpackung des gesamten Monorepos entspricht nicht unseren Anforderungen. Auch wenn wir "yarn" im Image des Microservice ausführen, möchten wir dort keine Symlinks haben, sondern nur eine normale Abhängigkeit.

Die Lösung hier muss nicht das Erstellen einer Garn.lock-Datei pro Arbeitsbereich sein, es könnte auch ein Garnbefehl sein, der beim Packen eines bestimmten Arbeitsbereichs hilft, eine Garn.lock-Datei für einen Arbeitsbereich bei Bedarf generieren usw. ..

Hoffe, es hat geholfen, den Anwendungsfall zu klären.. 🍻

@netanelgilad vielen Dank für Details. Es hilft zu verdeutlichen, dass es in Ihrem Anwendungsfall eher darum geht , einzelne Pakete für die Produktion oder Entwicklung in Docker-Containern zu veröffentlichen. Bitte beteiligen Sie sich an der Diskussion in #4521, damit wir mit der Konsolidierung beginnen können.

Ich kann zwar die Verwendung einzelner Sperrdateien sehen, sie sind jedoch nicht erforderlich. Wenn Sie docker aus dem Stammverzeichnis des Repos mit dem -f Flag ausführen, das auf die einzelnen Dateien zeigt, haben Sie das gesamte Repo als Kontext und können die Pakete package.json und Garn.lock aus dem Stammverzeichnis kopieren.

Sie benötigen nur die package.json für die Pakete, die Sie im Image erstellen, und Garn installiert nur Pakete für die package.json-Dateien, die Sie in die Dateien kopiert haben, obwohl die Garn.lock noch viel mehr enthält.

EDIT: Damit gesagt. es bewirkt, dass der Docker-Cache nicht für Paketänderungen in einem Paket verwendet wird, obwohl er nicht im Build enthalten ist

4206 ist verwandt/dupliziert, und der dort beschriebene Anwendungsfall ist genau das Problem, mit dem wir konfrontiert sind:

Nehmen wir an, wir haben zehn verschiedene Pakete. Wir möchten, dass sie alle in ihrem eigenen Repository leben, damit die Leute bei Bedarf unabhängig daran arbeiten können, aber wir möchten sie auch bei Bedarf miteinander verknüpfen können. Dazu haben wir ein Mega-Repository mit einem Untermodul für jedes Paket und eine package.json, die jedes dieser Untermodule als Arbeitsbereich referenziert.

Ich habe ähnliche Probleme mit Arbeitsbereichen. Mein Projekt ist ein web-app welches von vielen lokalen Paketen abhängt:

web-app/
|--node_modules/
|--packages/
|  |--controls/
|  |  |--src/
|  |  |--package.json
|  |--utils/
|     |--src/
|     |--package.json
|--src/
|--package.json
|--yarn.lock

Die Workspace-Pakete controls und utils werden nicht veröffentlicht und von Pfaden verwendet. Das Problem ist, dass ich das Paket controls ( yarn pack ) freigeben muss und es nicht selbst erstellen/testen möchte. Das heißt, ich möchte yarn install innerhalb von web-app/packages/constols/ . Bei Arbeitsbereichen wird die Datei web-app/yarn.lock obersten Ebene zusammen mit der Datei web-app/node-modules/ obersten Ebene verwendet. Es installiert also alle Pakete anstelle einer Teilmenge, die in web-app/packages/controls/package.json . Aber ich muss überprüfen, ob mein Paket alle erforderlichen Abhängigkeiten in seinen eigenen package.json und nicht durch das Auffüllen fehlender Deps aus anderen Arbeitsbereichen funktioniert.

Es gibt 2 mögliche Lösungen:

  1. Wenn es nicht root ist, verwenden Sie yarn.lock root, aber installieren Sie nur Pakete, die in local package.json .
  2. Suchen Sie nicht nach Konfigurationen der obersten Ebene, sondern nach .yarnrc/.npmrc .

Auch damit zu kämpfen. Wir haben ein Angular-CLI-Projekt neben unserer API, sodass sie sich im selben Repository befinden und versuchen, das Frontend an Heroku zu übertragen.

Wir verwenden ein Buildpack, das Heroku anweist, zuerst zum Frontend-Repository zu springen: https://github.com/lstoll/heroku-buildpack-monorepo

Das Problem ist, dass es kein yarn.lock in diesem nohoist Paket gibt, also wird Heroku einfach mit npm installiert und wir haben am Ende alle neuen Pakete und nicht die gesperrten

Sie können einfach die globale Datei "garn.lock" mit den einzelnen Paketen verwenden. Ich bin vor kurzem so an mein Dockerfile herangegangen:

WORKDIR /app
ENV NODE_ENV=production

ADD yarn.lock /app/
ADD package.json /app/

# Only copy the packages that I need
ADD packages/my-first-package /app/packages/my-first-package
ADD packages/my-second-package /app/packages/my-second-package

RUN cd /app && yarn install --frozen-lockfile

Dadurch werden nur Abhängigkeiten installiert, die tatsächlich von den beiden kopierten Paketen verwendet werden und nicht von anderen.

Ich habe einen Build-Prozess, bei dem ich zuerst ein Release-Artefakt aus einem Paket erstellen möchte und dann keine seiner Abhängigkeiten installiert haben. Dies ist mit dem mehrstufigen Build von Docker ziemlich einfach

  1. Fügen Sie Docker nur Garn.lock, package.json und das UI-Paket hinzu
  2. yarn install --frozen-lockfile ausführen
  3. Führen Sie den Build-Prozess aus
  4. Starten Sie eine neue Phase und fügen Sie Garn.lock, package.json und die erforderlichen Laufzeitpakete/Workspace-Ordner hinzu
  5. Mache COPY --from=<stage> für das gebaute Artefakt
  6. Führen Sie yarn install --frozen-lockfile und stellen Sie einen RUN Befehl bereit.

Und am Ende erhalten Sie einen kleinen Container, der nur die Abhängigkeiten enthält, die in Ihrer Garn.lock-Datei angegeben und in der Produktion benötigt werden.

@johannes-scharlach
Ich habe am Ende eine fast identische Methode verwendet, die Sie beschreiben. mehrstufiger Build ist ein guter Tipp :).

@connectdotz Ich denke, dass dieses Problem von meiner Seite aus geschlossen werden könnte und wir weiter an Problem #4521 arbeiten können. Da die Hauptdatei "garn.lock" mit einer Teilmenge der Pakete funktionieren könnte, scheint eine Garn.lock pro Arbeitsbereich nicht erforderlich zu sein (obwohl ich immer noch denke, dass dies ein besserer Entwicklungsworkflow sein könnte 😉 ). Aber das Problem in #4521 ist immer noch wichtig, denn in der Lösung, zu der wir hier gekommen sind, müssen wir jeden Dependency-Workspace im Dockerfile erwähnen, obwohl Garn die Interdependenzen kennen sollte und wissen sollte, wie ein bestimmter Workspace "Hersteller" ist.

Ich habe die letzten Tage damit verbracht, unser Monorepo zunächst in Lerna- und dann Yarn-Workspaces umzuwandeln. Yarn hat im Allgemeinen zuverlässiger funktioniert und ist sehr nah an dem, was wir brauchen, besonders mit der kürzlichen Einführung von yarn workspaces run <script> und anderen netten Dingen wie wsrun .

Das einzelne yarn.lock ist jedoch ein Schmerzpunkt:

  • Ich bin mir nicht sicher, wie wir unsere vorhandenen Lockfiles korrekt zu einem einzigen migrieren, siehe https://github.com/yarnpkg/yarn/issues/6563. Wir haben dort Zehntausende von Zeilen und das Hinzufügen vorhandener Pakete als Arbeitsbereiche führte zu vielen subtilen Versionsproblemen.
  • Das Installieren von Abhängigkeiten nur in einem bestimmten Paket ("de-hoisting" / "vendoring") Dockerized Build wird nicht gut unterstützt, siehe oben (https://github.com/yarnpkg/yarn/issues/5428#issuecomment-403722271) oder https: //github.com/yarnpkg/yarn/issues/4521.

Was halten Sie davon, dass Yarn-Workspaces nur ein winziger Kern sind – eine Deklaration von Paketen ohne spezifische Funktionalität. Zum Beispiel:

  • Wenn Sie ein Skript in Ihren Arbeitsbereichen ausführen möchten, würden Sie yarn workspaces run <script> tun.
  • Wenn Sie eine einzelne Sperrdatei und ein Hochziehen wünschen (sind die beiden notwendigerweise miteinander verbunden?), wäre dies Ihr Stamm package.json :
    json "workspaces": { "packages": ["packages/*"], "hoistDependencies": true }
  • Wenn Sie Ihre aktuellen Sperrdateien in eine hochgezogene Struktur migrieren möchten, würden Sie yarn workspaces hoist-dependencies ausführen.

Etc. Dies sind nur Beispiele und in der Praxis würden einige Funktionen wahrscheinlich Opt-out statt Opt-in (zum Beispiel Menschen einen einzigen erwarten yarn.lock jetzt und Heben) , aber die allgemeine Idee ist , dass die Arbeitsbereiche würden eine leichte Grundlage für Repository-weite Aufgaben sein.

Was denken Sie?

Ich glaube, das Problem, das diese Funktionsanforderung anspricht, ist das gleiche wie in #4521. Ein Befehl, der im Wesentlichen das tut, was @johannes-scharlach beschreibt, wäre sicherlich machbarer als eine Sperrdatei pro Arbeitsbereich.

Derzeit ist auch ein RFC für verschachtelte Arbeitsbereiche geöffnet , der dieser Funktionsanforderung ähnlich klingt, obwohl ich glaube, dass er ein anderes Problem löst.

Was halten Sie davon, dass Yarn-Workspaces nur ein winziger Kern sind – eine Deklaration von Paketen ohne spezifische Funktionalität?

Die Arbeitsbereiche werden sich nicht drastisch ändern, ich denke, wir sind mit ihrer aktuellen Benutzeroberfläche zufrieden.

Wenn Sie ein Skript in Ihren Arbeitsbereichen ausführen möchten, würden Sie yarn workspaces run <script> tun

Das ist bereits möglich (v1.10, #6244).

Wenn Sie Ihre aktuellen Sperrdateien in eine hochgezogene Struktur migrieren möchten, führen Sie yarn workspaces hoist-dependencies .

Da wir die Arbeitsbereichsoberfläche nicht ändern, wäre das Gegenteil der Fall ( dehoistDependencies ).

Was ich daran nicht mag, ist, dass es ein technisches Verhalten (Heben) nimmt und versucht, es in ein semantisches Verhalten umzuwandeln. Sie sollten sich auf die User Story konzentrieren und dann die Implementierung herausfinden und nicht das Gegenteil.

In diesem Fall denke ich, dass Ihr Anwendungsfall ("Abhängigkeiten nur in einem bestimmten Paket installieren") besser gelöst werden könnte, indem Sie yarn --focus .

Ich denke, die Kernfrage ist, ob das Hochziehen und eine einzelne yarn.lock Datei für Arbeitsbereiche unbedingt erforderlich sind. Ich meine, ist das, was sie wirklich definiert, oder ist es "nur" das erste Merkmal, das sie historisch haben?

In unserem Anwendungsfall wäre das beste hypothetische Verhalten von Arbeitsbereichen beispielsweise:

  • Heben Sie node_modules zur Entwicklungszeit für Effizienz auf.
  • Bewahren Sie lokale yarn.lock Dateien für den Build auf (wir erstellen bestimmte Pakete in Docker, was auch andere in diesem Thread erwähnt haben) und auch damit Pakete ihre spezifischen Versionen sperren können. Siehe auch #6563.
  • Führen Sie Skripte über yarn workspaces run <script> auch wenn Sie kein Hochziehen benötigen (oder vermeiden müssen).

Das Heben kann mit nohoist deaktiviert werden, run kann "deaktiviert" werden, indem der Befehl einfach nicht verwendet wird, aber es ist nicht möglich, die einzelne yarn.lock Datei zu "deaktivieren", und ich' Ich bin mir nicht sicher, ob es ein so wichtiges Feature ist, dass es nicht deaktiviert werden kann oder ob es einfach noch nicht genug angefordert wurde :)

Ich denke, der beste Weg, dies zu lösen, wäre yarn install --app-mode package@version

Auf diese Weise können Sie einfach die Workspace-Sperrdateien kopieren, wenn Sie Ihre App in einer bestimmten Version veröffentlichen, und die Installation in app-mode respektiert die gebündelte Sperrdatei.

Yarn muss nicht die gesamte Lockfile installieren; es sollte leicht in der Lage sein, nur den Teil des Abhängigkeitsgraphen zu extrahieren, der für dieses Paket relevant ist.

Tatsächlich könnte dies sogar jetzt noch ziemlich einfach sein:

  • Laden Sie die Paket-ZIP-Datei direkt aus der Registrierung herunter (Garn hat kein Äquivalent, npm tut es: npm pack package@version )
  • entpacke das gzip in node_modules/package
  • cd in node_modules/package
  • Führen Sie von dort das Garn install --production aus (es wird die gebündelte Lockfile respektiert)

Bearbeiten: Leider ist dies alles falsch, da die Workspace-Sperrdatei nicht die Versionen von Paketen im Workspace enthält, die möglicherweise Abhängigkeiten des App-Pakets sind. Beim Erstellen von App-Sperrdateien aus Workspace-Sperrdateien müsste etwas komplizierter sein als das Kopieren.

Ich bin mir nicht ganz sicher, ob separate Lockfiles die Antwort sind, aber ich habe ein ähnliches Problem. Ich habe ein Monorepo mit einer CLI und einem Backend eingerichtet. Die CLI erfordert einige plattformspezifische Pakete, die nur auf Desktop-Computern mit einem bestimmten Setup funktionieren. Auf der anderen Seite muss ich meine API in ein Docker-Image einbauen können, was bei der aktuellen Implementierung von Workspaces grundsätzlich unmöglich ist.

Sehr ähnlicher Anwendungsfall wie @samuela hier! Dieser wäre enorm hilfreich!

Mein Anwendungsfall mag im Vergleich zu den anderen "echten" lächerlich erscheinen. Aber ich habe ein Monorepo für einige Utils - in diesem Fall reagieren Hooks - in packages/* .

Ich habe einen zweiten Arbeitsbereich neben packages/* , und das ist local/* . Dies ist eigentlich auf gitignore, und die Idee ist, dass Entwickler im Unternehmen dort tun können, was sie wollen, zum Beispiel create-react-app Apps dort einfügen und die Hooks während der Entwicklung testen.

Nun, obwohl die local/* Pakete auf gitignore liegen, ist das Root yarn.lock einfach aufgebläht und verschmutzt - und in git eingecheckt - wegen der lokalen Workspaces.

Was ich mir wünschen würde, ist eine Möglichkeit anzugeben, dass einige Arbeitsbereiche bestimmte Sperrdateien verwenden sollen, z. B. eine Zuordnung wie folgt:

  "workspaces": {
    "packages": [
      "packages/*",
      "local/*"
    ],
    "lockfiles": {
      "local/*": "./local.yarn.lock"
    }
  }

Oder sogar eine Möglichkeit, anzugeben, "nichts aus _diesem_ Arbeitsbereich in die Sperrdatei einfügen".

Aber ja, meiner ist überhaupt kein ernsthafter Anwendungsfall :)

Ich bin mir nicht ganz sicher, ob separate Lockfiles die Antwort sind, aber ich habe ein ähnliches Problem. Ich habe ein Monorepo mit einer CLI und einem Backend eingerichtet. Die CLI erfordert einige plattformspezifische Pakete, die nur auf Desktop-Computern mit einem bestimmten Setup funktionieren. Auf der anderen Seite muss ich meine API in ein Docker-Image einbauen können, was bei der aktuellen Implementierung von Workspaces grundsätzlich unmöglich ist.

Sie haben es auf den Punkt gebracht – wie ich sehe, ist einer der Hauptvorteile der Datei "garn.lock" die Erstellung von Frozen-Dep-Produktions-Builds! Haben die Macher von Yarn das vergessen?

Ein weiteres Argument für die Lösung des Problems mit einer einzigen Sperrdatei ist der Besitz des Codes. Wenn Sie ein Monorepo haben, das so etwas wie die CODEOWNERS-Funktion von GitHub verwendet, ist es nicht möglich, einer Gruppe von Entwicklern das vollständige Eigentum an einem Paket zu übertragen. Das liegt daran, dass sie, wenn sie etwas in ihrem eigenen Arbeitsbereich installieren, unweigerlich die Sperrdatei auf Root-Ebene ändern. Diese Änderung muss von den Codebesitzern der Lockfile genehmigt werden, die sich bei einem ausreichend großen Monorepo von den Besitzern des ursprünglichen Arbeitsbereichs unterscheiden.

Ein weiterer Grund, eine Option zum Generieren von Sperrdateien pro Arbeitsbereich zu haben: Google App Engine weigert sich, einen Node-Dienst ohne Sperrdatei (NPM/Yarn) zu starten. Das sind ausgezeichnete Devops ihrerseits, aber ein Schmerz für uns. Bisher haben wir folgende Möglichkeiten:

  • Stellen Sie alle mit env vars bereit, die angeben, welchen Dienst wir meinen, und ändern Sie unseren yarn start (der einzige unterstützte Einstiegspunkt) in einen Branch basierend auf env vars
  • Lassen Sie das Build-Skript die Haupt-Sperrdatei in jeden Arbeitsbereich kopieren und stellen Sie nur den Dienst bereit, an dem wir interessiert sind. (Danke @johannes-scharlach)

Letztendlich denke ich, dass ein yarn install --workspace-lockfile Befehl, der pro Arbeitsbereich-Sperrdateien generiert wird, die beste Lösung wäre.

Eine Option für Sperrdateien auf Paketebene würde uns auch helfen. Unser Anwendungsfall ist ein wenig anders, wir testen einen neuen Weg, um lokale Abhängigkeiten zu verwalten.

Wir haben also bereits einige Mono-Repos, und wir haben einige Repos, die nur ein einzelnes Paket enthalten. Diese werden alle veröffentlicht und können daher zusammen verwendet werden, aber es gibt viele Male, in denen es sehr nützlich ist, sie lokal und symbolisch zu haben.

Aber einige Entwickler haben es schwer, Symlinks usw. zu verwalten, und so probieren wir ein Standard-Mono-Repo mit leerem Garn-Arbeitsbereich aus, das wir alle auf unsere Maschinen klonen, dann klonen wir Paket-Repos in dieses lokale Mono-Repo. Einige von uns haben vielleicht nur ein Paket Klone, andere vielleicht 5. Das ist super praktisch und macht lokale, repoübergreifende und abhängigkeitsübergreifende Entwicklung zum absoluten Kinderspiel.

Aber wir sind auf ein Problem gestoßen, das wir nicht lösen können: Das Bearbeiten von Abhängigkeiten aktualisiert nicht die lokale Garnsperre-Datei, es aktualisiert immer das Stammverzeichnis für das leere Mono-Repository, auf dem wir keine Abhängigkeiten aktualisieren (es hat alles unter /packages gitignored.

Es wäre großartig, eine Option zu haben, um Sperrdatei-Schreibvorgänge in das Mono-Repo-Root nicht zu heben und sie auf Paketebene schreiben zu lassen.

Als Anmerkung bin ich auch auf die Bereitstellungs- und Build-Probleme rund um Docker gestoßen, die andere erwähnt haben, und dies würde auch das lösen!

Diese Funktion wäre für mich auch sehr wertvoll. In meinem Fall habe ich ein Monorepo mit einigen Paketen, die auf verschiedenen Plattformen bereitgestellt werden. Eine ist eine Next.js-App, die mit Now.sh bereitgestellt wird, und die andere ist eine Reihe von Cloud-Funktionen, die in Firebase bereitgestellt werden.

In beiden Bereitstellungen wird der Quellcode gebündelt und zur Installation und Build in der Cloud hochgeladen. Das Fehlen einer yarn.lock Datei für die Quelle bedeutet, dass die Abhängigkeiten mit den Versionen in package.json installiert werden und keine Versionen gesperrt sind.

Ich würde auch gerne in jedem Arbeitsbereich Garn.lock-Dateien aktivieren.

Mir ist klar, dass Garn-Arbeitsbereiche hauptsächlich für Monorepos gedacht sind, aber unser Anwendungsfall ist dem von @LeeCheneler ziemlich ähnlich.

Grundsätzlich haben wir eine React-Komponentenbibliothek erstellt, die wir als Abhängigkeit in verschiedenen Projekten verwenden (die alle ihre eigenen Repos haben). Durch die Verwendung von Garn-Workspaces können wir problemlos auf die lokale Version der Komponentenbibliothek verweisen und Änderungen schnell an die lokale Version unserer anderen Projekte übertragen. Wir müssen auch die package.json nicht ändern, wenn wir in die Produktion gehen, da die Abhängigkeit library: "*" ohne Änderungen funktioniert. Unser einziges Problem ist, dass die Produktionsversionen jedes Projekts ohne Garnlock-Dateien unterschiedliche Spulenversionen verwenden könnten.

Ich muss mir vorstellen, dass dieses Problem bei allen Paketentwicklern auftreten würde, die Garn-Arbeitsbereiche verwenden.

Ein weiteres kritisches Problem bei einer Sperrdatei der obersten Ebene besteht darin, dass sie das Layer-Caching von Docker unterbricht. Normalerweise könnte man das Docker-Caching optimieren, indem man zuerst die package.json undgarn.lock kopiert. Wenn Docker keine Änderungen in diesen Dateien sieht, verwendet es eine vorherige Ebene. Wenn diese Sperrdatei jedoch eine einzige für das gesamte Monorepo ist, macht jede Änderung in einem Paket den Cache ungültig. Für uns führt dies zu lächerlich langsamen CI/CD-Pipelines, bei denen jedes Paket ohne Cache gebaut wird. Es gibt andere Tools wie Lerna, die auf Paketänderungen prüfen, um bestimmte Skripte auszuführen. Dies wird auch unterbrochen, da eine Abhängigkeitsänderung in der Sperrdatei möglicherweise nicht berücksichtigt wird, um sich auf der obersten Ebene zu befinden.

Es tut mir leid, dieses (etwas alte) Problem anzusprechen, aber ich habe auch einen Anwendungsfall, in dem dies hilfreich wäre. Ich habe ungefähr 10 Microservices, die unabhängig gehostet und entwickelt werden, aber es wäre schön, ein zentrales Workspace-Repository zu haben, in dem Sie yarn install eingeben können, um Abhängigkeiten in allen Ordnern zu installieren und dann yarn start auszuführen um ein Skript auszuführen, das alle Microservices startet. Dies könnte mit einem relativ einfachen Skript erfolgen, aber es schien auch mit Garn-Arbeitsbereichen machbar zu sein, aber ich konnte es nicht zum Laufen bringen, während die Garn-Sperren in jedem Mikrodienst respektiert wurden

@nahtnam Ich denke, die Idee von Yarn 1.x Monorepo ist ein bisschen anders. Es geht nicht um unabhängige Projekte unter einem Dach, sondern um ein einzelnes großes Projekt, bei dem einige seiner Komponenten (Workspaces genannt) exponiert sind. Diese Komponenten sind nicht völlig unabhängig, können aber so verwendet werden: der Babel-Compiler als eine größere Einheit und preset-env als Untermodul. Außerdem sind sie in dem Sinne homogen, dass ihre Abhängigkeiten vereinheitlicht sind: Wenn einige Pakete von core-js abhängen, sollte es in jedem einzelnen von ihnen dieselbe core-js Version sein, weil das nicht möglich ist sperren Sie verschiedene Versionen mit einer einzigen Root-Sperrdatei, und es macht auch keinen Sinn, dass Projektteile von verschiedenen Versionen abhängen. Und da es sich um ein Projekt handelt, werden alle seine Komponenten automatisch mit dem Stamm node_modules verknüpft, was für völlig unabhängige Projekte seltsam ist.

Wenn Sie also ein Paket von Microservices entwickeln (die unabhängig sind und einige von ihnen seit Jahren nicht mehr angerührt werden, während andere erstellt / aktualisiert werden, möglicherweise von verschiedenen Teams entwickelt), sollten sie persönliche Sperrdateien ohne Root haben lock (das Docker-Problem geht auch hier). Die Frage ist nur, welches Tool beim Ausführen von Skripten hilft. Lerna könnte eine Antwort sein, da es nicht an das Garn gebunden ist.

Die Frage ist nur, welches Tool beim Ausführen von Skripten hilft. Lerna könnte eine Antwort sein, da es nicht an das Garn gebunden ist.

@the-spyke Nicht nur das. yarn workspaces löst auch und verknüpft Module für die Entwicklung auf die gleiche Weise wie npm link , was der Hauptgrund dafür ist, dass wir es verwenden. npm link funktioniert in einigen Fällen nicht richtig.

@the-spyke Danke! Aus irgendeinem Grund dachte ich, es sei umgedreht (Lerna vs. Garn-Arbeitsbereiche). Ich habe mir lerna angesehen und es sieht so aus, als ob es mein Problem löst

Letztendlich habe ich Arbeitsbereiche für jedes einzelne Projekt verwendet, an dem ich arbeite, weil es so einfach ist, ein separates utilities Paket zu haben, das ich bei Bedarf aktualisieren kann (obwohl es veröffentlicht ist) und die Tatsache, dass Ich muss Abhängigkeiten nicht neu installieren, wenn ich ein Paket forken möchte (was mir im Wesentlichen ermöglicht, an zwei Branches gleichzeitig zu arbeiten, was für mich unbekannt war) und wenn ich ein Paket aus meinem utilities möchte package.json des zweiten Pakets hinzuzufügen (aber das ist natürlich eine gute Idee im Falle einer separaten Installation und ist erforderlich) für automatische IDE-Importe) ; alles funktioniert einfach. @the-spyke macht einen guten Punkt, vielleicht ist independent projects under one roof nicht der Zweck von Arbeitsbereichen, und doch ist es so ziemlich das, was ich hier zu tun scheine: Ich habe ein einzelnes monorepo-base Repository, das schließt den Ordner packages , während jeder Ordner unter packages ein separates unabhängiges Git-Repository ist.
image
Das bringt mich natürlich zum Thema dieses Threads; Da ich nicht alle Pakete als ein Repository festschreibe, ist Root-Level yarn.lock bedeutungslos. Ich habe --no-lockfile , um alles zu installieren, und bin kürzlich auf ein Problem mit widersprüchlichen Versionen von class-validator . Im Moment werde ich alle Deps auf bestimmte Versionen sperren (ehrlich gesagt, dieses Maß an Kontrolle macht für mich mehr Sinn) und sehen, wie es funktioniert. Ich werde das ganze Profil noch einmal lesen, vielleicht gibt es ein paar Tipps, die ich für meinen Anwendungsfall verwenden könnte.

PS.
yarn why funktioniert nicht ohne Lockfile, und ich habe bemerkt, dass einige Leute Probleme mit App Engine erwähnen. Ich nehme an, wenn jedes Paket ein separates Repository ist, könnte die Sperrdatei jedes Mal bei der Installation generiert werden (ohne sie zu VCS hinzuzufügen)? Bin mir in diesem speziellen Fall nicht sicher.

Leider wird die von @johannes-scharlach vorgeschlagene Lösung sehr chaotisch, wenn Ihr erstelltes Image Laufzeitknotenmodule erfordert, die nicht in einem Build-Ordner enthalten sind, da Sie genau herausfinden müssen, welche Module zum Ausführen erforderlich sind, und sie mühsam dorthin kopieren müssen die letzte Bauphase.

(etwas abseits vom Thema) @GrayStrider Sie können auch das Feld "resolutions" in package.json verwenden - es ist die einzige Möglichkeit, eine Version einer verschachtelten Abhängigkeit zu erzwingen, z wie tief verschachtelt. Dies kann jedoch zu sehr subtilen Fehlern führen, die schwer zu erkennen sind.

Hier ist eine Lösung, auf die wir gekommen sind – mit minimalen Auswirkungen auf den bestehenden Docker-Workflow.

  1. ln project/yarn.lock packages/package1/yarn.lock - Erstellen Sie einen harten symbolischen Link vom Stamm yarn.lock in jedes Paket.
  2. Füge COPY yarn.lock . zu jedem packages/package1/Dockerfile
  3. yarn install in Docker

Vorteile :

  • Sie müssen nicht Ihr gesamtes Monorepo in eine Bildebene kopieren
  • Sie müssen Ihre Dockerfiles auf Paketebene nicht zu einem einzigen Dockerfile im Stammverzeichnis zusammenführen
  • Erfüllt grundsätzlich die Anforderung von Workspace Lockfiles

Nachteile :

  • --frozen-lockfile funktioniert nicht. Da die Workspaces-Pakete nicht in yarn.lock , sieht Garn ein Paket, das Sie zu package.json "hinzugefügt" haben und das nicht in yarn.lock

Dies ist jedoch ein kleiner Nachteil, da Sie ihn umgehen können, indem Sie als ersten Schritt in Ihrer CI/CD-Pipeline einen yarn --frozen-lockfile ausführen

Bearbeiten:
Abgesehen davon denke ich wirklich, dass die Garndokumente zur Installation etwas klarer sein könnten, wie die Sperrdatei vom Paketauflösungsprozess verwendet wird.

Bearbeiten:
Es stellt sich also heraus, dass Git keine Hardlinks unterstützt, sondern nur weiche Symlinks, daher wird diese Strategie nicht funktionieren.

Eine andere Alternative besteht darin, einfach einen Precommit-Githook zu verwenden, um die yarn.lock in jeden Ihrer Arbeitsbereiche zu kopieren. Dies ist nicht ideal, da es immer noch Probleme bei der Bereitstellung von Ihrem lokalen Computer aus ermöglicht.

@dan-cooke vielen Dank für Ihre Einblicke, sehr geschätzt!

@dan-cooke, dies unterbricht das Layer-Caching von Docker, da eine neue Abhängigkeit in einem beliebigen Arbeitsbereich die Installationsebene für alle Dockerfiles ungültig machen würde.

@migueloller Wenn sich die Installationsebene nicht ändern darf, sollten Sie nicht eine Sperrdatei für alle Pakete verwenden. Das Abflachen und Hochziehen von Abhängigkeiten in eine einzige riesige Liste ist der ganze Zweck von Workspaces. Es ist nicht so, dass er den Docker-Cache "unterbricht", der Cache wird ungültig gemacht, weil in package.json keine echten Abhängigkeiten angegeben sind, sodass der endgültige Code Ihres Pakets vom Inhalt von yarn.lock abhängt. Als Ergebnis müssen Sie alle Pakete bei jeder Änderung in yarn.lock erstellen und Docker macht alles richtig. Und es ist nicht wie where every package is built without the cache weil alle Builds den Layer mit yarn install wiederverwenden könnten (wahrscheinlich müssen Sie dies einrichten).

@migueloller
Richtig. Glücklicherweise fügen wir nicht oft neue Abhängigkeiten hinzu, daher wird dies höchstens einmal pro Sprint ein Problem sein.

Und selbst dann ist es (für uns) ein kleiner Preis für reproduzierbare Abhängigkeiten in Docker

@the-spyke, in der Tat. Aus diesem Grund geht es bei diesem Problem darum, eine individuelle Lockfile pro Paket zu haben. Auf diese Weise wird die zwischengespeicherte Schicht nur ungültig gemacht, wenn sich die Abhängigkeiten des Pakets ändern, und ist unabhängig von anderen Paketen.

Vielleicht lohnt es sich auch, diese Diskussion auf npm selbst zu verschieben, das ab v7.0 auch Arbeitsbereiche unterstützt.

Ich habe nach verwandten Themen recherchiert und möchte meinem obigen Kommentar einige Klarstellungen hinzufügen (hauptsächlich für weniger erfahrene Entwickler, nehme ich an, da die Probleme, mit denen ich konfrontiert war, zum Teil darauf zurückzuführen waren, dass ich die Bedeutung von lockfile ).

"Sperren aller Abhängigkeiten zu einer bestimmten Version" wird als " Pinning " bezeichnet; leider wird es nicht verhindern , dass Dinge von möglicherweise brechen , wenn Unter -Abhängigkeit Aktualisierungen (letzte Absätze des Artikels hier ), die ich nicht berücksichtigt. Genau das wollte lockfile verhindern.

Ich habe in der Vergangenheit bei mehreren Gelegenheiten mehr als genug Stunden damit verbracht, Updates zu veröffentlichen; Ich werde mit der Verwendung von lockfile in Monorepo experimentieren, da ich mich lieber mit Zusammenführungskonflikten und organisatorischen Kopfschmerzen beschäftige als mit unsichtbaren Fehlern, die durch kleinere Updates verursacht werden.

Oben gesagt, ich freue mich sehr auf jeden Fortschritt in dieser Angelegenheit

@migueloller Individuelle Lock-Files bedeuten individuelle Yarn Monorepos. Sie können keine Sperrdatei für einen Arbeitsbereich haben, da sie die Einheitlichkeit im Monorepo unterbricht. Wenn Sie dies tun möchten, verlassen Sie die ursprüngliche Idee von Yarn Monorepo: Es geht darum, Deps in einer flachen Liste im Stamm zu vereinheitlichen, zu heben und zu reduzieren, anstatt verschiedene Versionen (und sogar ganze Unterbäume) in verschiedenen Arbeitsbereichen zu haben .

@the-spyke, aber im ursprünglichen Problem geht es genau um das Gegenteil. Eine Sperrdatei pro Arbeitsbereich.

Ich kann nicht verstehen, wie Sie pro Arbeitsbereich keine Sperrdatei haben können.

Es bricht die Einheitlichkeit im Monorepo? Sicher für die Entwicklung. Aber der ganze Zweck von geteilten Abhängigkeiten geht aus dem Fenster, wenn Sie leichtgewichtige Mikrodienste von jedem Ihrer Arbeitsbereiche aus bereitstellen müssen

Gemeinsame, hochgezogene Deps machen nur in der Entwicklung Sinn.

Damit ein Arbeitsbereich in Docker leben kann, ist eine Sperrdatei erforderlich.

@dan-cooke Wie ihr seht hatte ich dieses Problem auch 2018, aber jetzt bin ich anderer Meinung.

Sie sagen Docker und Microservices. Aber was ist, wenn ich ein reguläres npm Paket entwickle? Ich habe keinen production Abhängigkeits-Unterbaum zum Anheften, da sie vom Endbenutzer gemäß meiner dependencies Spezifikation bereitgestellt werden. Was ich also möchte, ist, meine Entwicklungserfahrung zu maximieren, und das, was Monorepos und Yarn Workspaces perfekt können.

Gleichzeitig gibt es 2 mögliche Situationen, wenn Sie Microservices (MSs) entwickeln:

  1. Eigenständige Projekte. Einige MSs befinden sich in der Entwicklung, einige wurden seit Jahren nicht mehr angerührt. In diesem Fall sind sie völlig unabhängig. Es ist möglich, UserService mit [email protected] und MessagesService mit [email protected] . Das ist keine einfache Welt, in der Sie einfach Ordner aus Arbeitsbereichen mit dem Stamm node_modules verknüpfen. Es macht also keinen Sinn, eine Root-Sperrdatei zu haben. Erstellen Sie separate Dateien (Roots) und verwalten Sie sie unabhängig. Das nannte Multirepo in den Yarn-Dokumenten. Aber jetzt sagen Sie: "Ich möchte Aufgaben in verschiedenen Ordnern vom Stammordner aus ausführen". Und das ist ein ganz anderes Thema.

  2. Projekte mit einheitlichen Abhängigkeiten wie Jest/Babel/etc. Dafür wurden Workspaces gemacht, aber in MSs gibt es zusätzliche Anforderungen. Während der CI-Phasen wie Linting und Testing funktioniert alles gut, weil es genauso funktioniert wie auf einem Entwicklercomputer: deps wird von Yarn in root node_modules installiert und abgeflacht. Nur zusätzlich, dass Sie wahrscheinlich die yarn install Phase zwischenspeichern, um gleichzeitige Builds zu beschleunigen.

    In der Produktion ist das ganz anders: ab da braucht man nur deps für einen Workspace und endend mit wie installiere ich das utils Paket? Soll es verlinkt oder als Tarball heruntergeladen werden? Was Sie also wirklich brauchen, sind keine Lock-Dateien pro Workspace, sondern einen Befehl wie yarn install --prod <workspace> , den Sie ausführen können, indem Sie einen Workspace angeben und der nur Produktionsabteilungen installiert und gleichzeitig andere nicht referenzierte Workspaces ignoriert. Wenn mein data WS von utils data WS abhängt, aber nicht von logging WS, dann sollten logging selbst und seine Absätze nicht in node_modules . Ein ähnliches Ergebnis, aber eine völlig andere Herangehensweise an eine "Sperrdatei pro Arbeitsbereich".

    Wenn Sie Build-Pakete in einem Repository (npm, Arifactory, GutHub) veröffentlichen, können Sie ein ähnliches Verhalten erzielen, indem Sie einfach die Lock-Datei in einen Workspace kopieren und hier yarn install --prod ausführen. Es sollte vor einer veralteten Datei warnen, aber anstatt sie mit neuen Versionen von Grund auf neu zu erstellen, sollte es nur überschüssige Deps entfernen (nur versucht und sieht echt aus). Sollte mit Offline Mirror noch besser und robuster sein.

    Und am Ende haben Sie Focused Workspaces genau für Multirepos implementiert.

Also, was ich gesagt habe, dass das Problem vielleicht nicht so aussieht, wie es ist.

@the-spyke
Ich verstehe, was du sagst. Ich denke, es kommt definitiv darauf an, wie dieses Ergebnis erreicht wird. Vielleicht ist eine Lockfile pro Arbeitsbereich nicht wirklich der beste Weg, um das gewünschte Ergebnis zu erzielen. Sie machen einige gute Punkte.

Es ist definitiv keine "One-Size-Fits-All"-Lösung

@the-spyke, du bringst gute Punkte mit. Vielleicht muss mehr darüber nachgedacht werden, welche Probleme Yarn-Arbeitsbereiche lösen sollen und ob die Verwendung zur Verwaltung großer Monorepos auf dieses Design ausgerichtet ist.

Ich bin gespannt, wie Sie ein Szenario wie dieses lösen würden:

.
└── packages
    ├── app1
    ├── app2
    ├── lib1
    ├── lib2
    └── lib3

lib3 ist eine gemeinsam genutzte Bibliothek und hängt von app1 und app2 . lib1 wird nur von app1 und lib2 wird nur von app2 . Basierend auf Ihren Vorschlägen sollten sich lib1 und app1 in ihrem eigenen Arbeitsbereich mit ihrer eigenen Sperrdatei befinden und dasselbe mit lib2 und app2 . Die Frage ist nun, was mit lib3 zu tun ist, wenn _beide_ app1 und app2 abhängen? Vielleicht könnte man es so machen, dass beide Arbeitsbereiche ( app1 und app2 ) lib3 zu ihrem Arbeitsbereich hinzufügen und dann yarn install in jeder App ausführen? Lässt Garn dies zu? Gibt es Konflikte, wenn man sowohl app1 als auch app2 lokal in der Entwicklung ausführen möchte (vielleicht ist app1 eine React-App und app2 eine GraphQL-API) ? Das klingt, als könnte es funktionieren.

Die nächste Frage wäre: "Wie kann man die Vorteile des Hebens mit dieser Methode nutzen?" Wenn beispielsweise app1 und app2 viele gemeinsame Abhängigkeiten teilen, wäre es schön, sie hochzuheben. Ich kann jedoch sehen, dass dies außerhalb des Geltungsbereichs liegt und ein Problem ist, das von Yarn PnP gelöst werden muss (es kopiert keine Dateien in node_modules und hat stattdessen einen gemeinsamen Cache).

Ich werde das mal ausprobieren und werde berichten. Wenn das am Ende funktioniert, haben wir die Yarn-Arbeitsbereiche vielleicht die ganze Zeit falsch verwendet ...

EDIT: Ich habe es ausprobiert und es funktioniert.

Ich habe jetzt meine Haltung geändert und stelle fest, dass eine individuelle Lockfile pro Workspace zwar das erste ist, was mir bei der Verwaltung eines gesamten Monorepos mit Yarn-Workspaces in den Sinn kommt, dies jedoch möglicherweise nicht die richtige Frage ist. Eine bessere Frage könnte lauten: "Sind Yarn-Arbeitsbereiche für die Verwaltung eines Monorepo konzipiert?". Die Antwort lautet wie immer "es kommt darauf an".

Wenn Sie Babel sind und ein einziges Team am Monorepo arbeitet und sich alles im Gleichschritt ändern soll, dann ja, dafür wurden Yarn Workspaces entwickelt. Wenn Sie jedoch ein Unternehmen mit mehreren Teams sind und ein Monorepo verwenden, möchten Sie wahrscheinlich nicht das gesamte Monorepo mit einem einzigen Yarn-Workspace-Root verwalten. Sie möchten wahrscheinlich nur das Standardverhalten von Yarn oder mehrere Yarn-Workspace-Roots innerhalb des Monorepo verwenden. Dies hängt davon ab, welche Apps Sie erstellen, wie viele Teams es gibt usw.

Für uns wurde klar, dass wir für jede bereitstellbare Entität (in unserem Fall gibt es ein Dockerfile) ein separates yarn install für jede Entität erstellen wollen (ob Workspace-Root oder nicht). Dies schafft Klarheit über den Besitz von Code, ermöglicht isolierte Bereitstellungen, die in unterschiedlichen Takten erfolgen, löst Caching-Probleme mit Lockfiles und Docker usw. Dies hat jedoch einige Nachteile:

  • Was ist mit duplizierten node_modules-Paketen? Dies ist eine häufige Klasse von Problemen bei Monorepos, und obwohl Yarn-Arbeitsbereiche beim Heben helfen, ist dies keine allgemeine Monorepo-Lösung. Es gibt aber auch andere Lösungen. Dafür sorgt beispielsweise Yarn PnP. Sie können Lerna auch ohne Garn verwenden und die Option --hoist .
  • Was ist mit der Nützlichkeit der Ausführung von Befehlen in Arbeitsbereichen während der Entwicklung? Auch hier können Sie dies mit Yarn-Workspaces tun, aber das bedeutet nicht, dass man das gesamte Monorepo zu einem Yarn-Workspace-Stamm machen sollte. Die Erstellung der erforderlichen Tools und Skripte ist für jedes Team unterschiedlich und hängt von ihrem Monorepo ab. Yarn Workspaces wurde wahrscheinlich nicht als Monorepo-Task-Runner konzipiert. Man könnte versuchen, die Yarn-Workspaces ein wenig zu verbiegen, um diese Aufgabe zu erledigen (dh NPM-Skripte über das Monorepo mit yarn workspace ... ausführen), aber es ist wichtig zu bedenken, dass ein einzelner Workspace-Root für das gesamte Monorepo wahrscheinlich nicht funktioniert Gib dir, was du brauchst, es sei denn, du bist wie Babel, Jest, React usw.

Es gibt noch eine ganze Reihe anderer Probleme, die mit der Ausführung eines Monorepos einhergehen. Wie sieht es beispielsweise damit aus, Abhängigkeiten zu verfolgen und nur Dinge neu zu erstellen, die sich geändert haben, um Zeit in CI zu sparen? Yarn-Arbeitsbereiche könnten dabei helfen, indem Sie das Abhängigkeitsdiagramm abfragen lassen. Lerna macht dies zum Beispiel, um eine topologische Sortierung der ausgeführten Befehle zu ermöglichen. Mit Yarn v2 können Sie auch das Abhängigkeitsdiagramm abfragen. Das macht auch der Paketmanager PNPM. Aber ich würde argumentieren, dass man je nach Komplexität des Monorepo vielleicht Tools ausprobieren möchte, die dafür gebaut wurden (keine Paketmanager) wie Bazel , Pants , Buck usw.

@migueloller Aus Ihren Anforderungen sehe ich, dass Sie keine streng unabhängigen Pakete oder andere exotische Dinge benötigen, Sie möchten auch schlankere Entwicklerinstallationen. In diesem Fall sollten Sie mit regulärem Yarn Monorepo beginnen: einzelnes Root und alle Pakete als Arbeitsbereiche. Sie haben schnellere Installationszeiten, geringere Festplattennutzung und app1 verwendet lokal verknüpfte lib1 und lib3 . Der einzige Nachteil ist, dass der CI-Cache häufiger ungültig wird, da das Hinzufügen einer devDep zu lib1 die gemeinsamen yarn.lock aktualisiert. Aber normalerweise aktualisieren Sie Abhängigkeiten nicht so oft, um sich viele Gedanken über diesen Kompromiss zu machen.

lib1 kann von lodash@^4.5.0" and lib2 may depend on lodash@^4.10.0" abhängen. Im Falle von Monorepo möchten Sie eine einzelne Version von lodash verwenden, also Das Garn wird etwas neuesten kompatibel zu den beiden Planern wie `installieren [email protected] " gehievt Wurzel node_modules. Und im Falle eines Updates aktualisieren Sie diese einzelne einheitliche Version, sodass alle Arbeitsbereiche immer auf derselben Seite bleiben. Dies ist das gewünschte Verhalten.

Es gibt auch Situationen, in denen unabhängige Teams unabhängige Projekte entwickeln. In diesem Fall möchte proj1 möglicherweise bei [email protected] bleiben, wobei proj2 [email protected] und diese mit ihren eigenen Kadenzen aktualisieren. Natürlich können Sie dies erreichen, indem Sie strengere Bezeichner wie lodash@~4.5.0 , aber dies kann die Abhängigkeit der zweiten Ebene immer noch zu früh aktualisieren. Im Großen und Ganzen können diese Projekte also völlig unabhängig sein, sie befanden sich zufällig in einem Git-Repo. In diesem Fall gibt es keinen Grund, sie als Yarn Monorepo zu binden und Unabhängigkeit für eine gemeinsame Lock-Datei abzuwägen. Behandeln Sie sie einfach als das, was sie sind: getrennte Projekte mit ihrem unabhängigen Leben. Und das nennt man Multirepo. Unter Unix sind alle Ihre Verzeichnisse unter / , aber das bedeutet nicht, dass alle möglichen JS-Projekte auf Ihrem PC ein Monorepo sein sollten :-)

Das Erstellen eines minimal möglichen Docker-Images für den Produktionseinsatz hat nichts mit Yarn zu tun, aber Sie können Yarn zwingen, ein Entwicklungsartefakt namens yarn.lock wiederzuverwenden und Ihnen auch bei dieser Aufgabe zu helfen.

@the-spyke, in diesem Beispiel habe ich nur 3 Arbeitsbereiche verwendet, aber in unserem aktuellen Repository haben wir über 20 Arbeitsbereiche mit einer Kombination aus Bibliotheken und bereitgestellten Workloads sowohl für das Front-End als auch für das Back-End. So wie ich es jetzt sehe, haben wir ein Monorepo (oder was Sie Multirepo nennen), bei dem es wahrscheinlich sinnvoll ist, mehrere Yarn-Workspace-Roots mit unabhängigen Lockfiles zu haben. Wir denken daran, eine einsetzbare Einheit als Trenneinheit zu verwenden, sie passt gut zu Lockfiles.

Ich denke, was diese Arbeit für mich sehr gut macht, ist die Tatsache, dass Yarn-Workspaces Pfade außerhalb des Workspace-Stamms unterstützen, obwohl der ursprüngliche Blogbeitrag etwas anderes sagt. Zum Beispiel können Sie dies haben:

{
  "workspaces": [
    "../lib1",
    "../lib3"
  ]
}

Wir haben den gleichen Anwendungsfall als @migueloller und eine mögliche Idee für Yarn ist mehrere Sätze von Arbeitsbereichen, wie dies zu unterstützen:

{
  "workspaces": {
    "frontend-app": ["frontend", "common"],
    "backend-app": ["backend", "common"]
  }
}

Yarn würde zwei zusätzliche Sperrdateien verwalten (ich stelle mir vor, dass die Hauptdatei yarn.lock noch existieren würde):

.
└── monorepo/
    ├── yarn.frontend-app.lock
    ├── yarn.backend-app.lock
    └── packages/
        ├── frontend
        ├── backend
        └── common

Beim Erstellen eines Docker-Images z. B. für das Frontend erstellen wir einen Kontext (z. B. über tar ), der

.
└── <Docker build context>/
    ├── yarn.frontend-app.lock
    └── packages/
        ├── frontend
        └── common

Worüber ich nicht intensiv nachgedacht habe, ist, ob es möglich ist, die richtigen Versionen von Abhängigkeiten zu installieren (Link in node_modules ), wenn Frontend und Backend unterschiedliche Versionen sperren. Aber rein aus der übergeordneten Sicht sind wahrscheinlich zweidimensionale Yarn-Arbeitsbereiche das, was wir suchen.

(Ähnliches wurde auch hier gepostet.)

Es sieht so aus, als ob Sie keine Sperrdatei pro Arbeitsbereich benötigen, sondern für die Bereitstellung node_modules pro Arbeitsbereich benötigen

@gfortaine , wenn Sie die Diskussion lesen, werden Sie feststellen, dass dies tatsächlich nicht der Fall ist. Der Grund für eine separate Sperrdatei hat nichts mit der Installation zu tun, sondern mit einer Sperrdatei, die sich nur ändert, wenn sich ein bestimmtes Paket ändert. Eine Sperrdatei der obersten Ebene ändert sich mit _jeder_ Änderung der Arbeitsbereichsabhängigkeit, aber eine Sperrdatei, die auf ein einzelnes Paket beschränkt ist, ändert sich nur, wenn sich die Abhängigkeiten von _diesem_ Paket ändern.

Erwähnenswert ist, dass dies im User-Land möglich ist. Mit dem @yarnpkg/lockfile Paket kann man die Sperrdatei der obersten Ebene analysieren und dann mit yarn workspaces info die Arbeitsbereichsabhängigkeiten bestimmen. Mit diesen Informationen kann man zusammen mit den package.json jedes Arbeitsbereichs eine Sperrdatei pro Arbeitsbereich generieren. Dann könnte man das als postinstall Skript im Repository einrichten, um diese einzelnen Sperrdateien mit der obersten Ebene synchron zu halten.

Ich könnte einen Versuch machen, dies zu bauen und mit meinen Ergebnissen Bericht zu erstatten.

Es sieht so aus, als hätte ich gerade diese Implementierung gefunden, wenn auch für pnpm: @pnpm/make-dedicated-lockfile

Hoffe das hilft

Mein Bedarf für dieses Verhalten (Versionierung pro Arbeitsbereich, aber immer noch Sperrdateien in jedem Paket) besteht darin, dass ich ein verschachteltes Monorepo habe, bei dem ein Teilbaum vollständig in ein anderes Repository exportiert wird, also unabhängig bleiben muss. Im Moment stecke ich mit lerna/npm und einer benutzerdefinierten Logik fest, um zu versuchen, Versionen auszugleichen. Wäre schön, wenn Garn (ich schätze, v2, da dort die verschachtelte Unterstützung liegt?) könnte sie alle gleichzeitig verwalten, aber die richtige Teilmenge des globalen Pinnings in jedem belassen.

Ein Postinstall-Skript könnte versuchen, die Sperrdateien direkt zu verwalten, nehme ich an. Klingt kompliziert, wäre aber so oder so schön.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

davidmaxwaterman picture davidmaxwaterman  ·  3Kommentare

MunifTanjim picture MunifTanjim  ·  3Kommentare

danez picture danez  ·  3Kommentare

baptistelebail picture baptistelebail  ·  3Kommentare

sebmck picture sebmck  ·  3Kommentare