Wenn Sie anfangen, über TypeScript-Monorepos nachzudenken, erweitern sich Ihre Möglichkeiten schnell. pnpm, bun, Turborepo, Nx, Changesets, Biome. Sie scheinen alle richtig zu sein, aber wenn man sie alle von Anfang an einbezieht, wird es schwer. Wenn Sie hingegen alles abschneiden, werden Sie später in Schwierigkeiten geraten.
Der Grund dafür, dass eine solche Diskussion schwierig zu organisieren ist, liegt darin, dass wir nur nach der „optimalen Lösung“ suchen, ohne die Prämissen zu berücksichtigen. Es ist besser, die allgemeine, leicht verständliche Lösung und die praktische Lösung für die vor Ihnen liegende Konfiguration zu trennen.
Dieses Mal werde ich die folgenden zwei Teile organisieren.
- Sichere Konfiguration beim Erstellen eines neuen TypeScript-Monorepos
- Realistische Konfiguration basierend auf den spezifischen Annahmen von
apps/web,apps/wxt,packages/ui,packages/core
Zuerst das Fazit
| Voraussetzungen | Erste Konfiguration zur Auswahl | Ergänzung |
|---|---|---|
| Neues generisches Monorepo. Zukünftig werden Paketfreigabe, CI-Optimierung und Docker-Integration berücksichtigt | pnpm workspace + Turborepo + TypeScript Project References + package.json von exports + Changesets | Das stabilste |
4 Paketkonfigurationen: apps/web, apps/wxt, packages/ui, packages/core. Ich verwende kein Docker. Veröffentlichen Sie keine freigegebenen Pakete auf npm | pnpm workspace + Biome + TypeScript Project References | Turborepo wird zu diesem Zeitpunkt nicht benötigt |
Bun stellt die Ausführungsumgebung, den Paketmanager und Tests bereit bun workspace ist ebenfalls ein Kandidat | Allerdings ist pnpm stark im Hinblick auf den sicheren Betrieb |
Kurz gesagt, pnpm + turbo ist stark in der allgemeinen Theorie. In diesem Fall ist jedoch workspace only ausreichend.
Allgemeiner Zweck, nicht schwierig
Wenn Sie ab 2026 ohne große Sorgen starten möchten, ist pnpm workspace die stabilste Grundlage. workspace wird standardmäßig bereitgestellt, lokale Paketverweise können mit workspace:-Protokoll explizit gemacht werden und Zielpakete können mit --filter erheblich eingegrenzt werden.
Verwenden Sie TypeScript-Projektreferenzen für Typgrenzen. In der offiziellen TypeScript-Dokumentation heißt es außerdem eindeutig, dass geteilte Projekte mithilfe von tsc --build die Erstellungszeit, die logische Trennung und die Reihenfolge der Abhängigkeiten verbessern können. Dies ist in Monorepo sehr effektiv.
Wenn Sie darüber hinaus Turborepo hinzufügen, verfügen Sie gleichzeitig über Aufgabendiagramm, Cache, parallele Ausführung und turbo prune. [Turborepos Aufgabeneinstellungen] (https://turborepo.dev/docs/crafting-your-repository/configuring-tasks) müssen nur um dependsOn und outputs zusammengestellt werden, und es gibt Raum für Wachstum, wenn das Repo wächst.
Wenn Sie ein Paket veröffentlichen möchten, passt natürlich auch Changesets hinein. pnpms Arbeitsbereichsdokumentation geht außerdem davon aus, dass ein spezielles Tool wie Changesets für die Versionierung von Paketen in einem Arbeitsbereich verwendet wird.
Mit anderen Worten, die allgemeine, nicht schwierige Lösung lautet wie folgt.
| Rolle | Empfehlung |
|---|---|
| Arbeitsbereichsverwaltung | pnpm workspace |
| Typgrenzen und inkrementelle Builds | TypeScript Project References |
| Aufgabenausführung, Parallelisierung und Caching | Turborepo |
| öffentliches Gesicht der Paketgrenze | exports von package.json |
| Versionierung / Änderungsprotokoll | Changesets |
| Fussel / Format | Biome oder ESLint + Prettier. Es ist jetzt einfacher, mit Biome zu beginnen |
Warum wird Turborepo in dieser Prämisse immer noch nicht benötigt?
Die Konfiguration ist dieses Mal ziemlich einfach.
packages/corepackages/ui -> packages/coreapps/web -> packages/ui, packages/coreapps/wxt -> packages/ui, packages/coreWenn die Abhängigkeiten auf dieser Ebene liegen, reicht es für den Betrieb aus, den Filter auf pnpm workspace und tsc -b auszuführen.
Beispielsweise erhöht sich in Situationen wie dieser plötzlich der Wert der Einbeziehung von Turborepo.
| Schmerz | Warum Turborepo funktioniert |
|---|---|
| Die gesamte Build-/Test-/Lint-Zeit ist lang | Caching und parallele Ausführung sind wirksam |
| Ich möchte die Abhängigkeitsreihenfolge von Aufgaben klären | dependsOn kann einen Graphen |
| Ich möchte CI | beschleunigen Remote-Cache funktioniert |
| Ich möchte nur die notwendigen Pakete für Docker | extrahieren turbo prune kann verwendet werden |
Wenn Sie es hingegen zu einem Zeitpunkt installieren, an dem Sie noch keine derartigen Probleme haben, ist es schwierig, den Wert zu erkennen, der über das Hinzufügen einer weiteren Konfigurationsdatei hinausgeht. Wenn Sie Docker deaktivieren, wird die Attraktivität von prune um ein Vielfaches geringer. Changesets ist auch nicht erforderlich, wenn Sie keine freigegebenen Pakete auf npm veröffentlichen.
Basierend auf dieser Prämisse ist es daher sinnvoll, mit pnpm workspace + Biome + TypeScript Project References zu beginnen.
So schneiden Sie Schichten
Bei dieser Vierteilung ist es wichtiger, Unklarheiten bei den Rollen zu vermeiden als bei der Werkzeugauswahl.
| Pfad | Dinge zum Verstauen | Dinge, die Sie nicht sagen sollten |
|---|---|---|
packages/core | Domäne, Schema, Validierung, API-Client, reine Funktion, Zustandsmodell | Benutzeroberfläche, Routing, Browser-API |
packages/ui | Umgebungsunabhängige React-Komponente/Hook | WXT-spezifische Verarbeitung, Router, Erweiterungsspeicher |
apps/web | Zusammenstellung als Webanwendung, Seite, Routing, Adapter | erweiterungsspezifische Umstände |
apps/wxt | Hintergrund-/Inhaltsskript, Browser-API, WXT-spezifische Einstellungen | Webspezifisches Routing, reine Logik, die in der gemeinsam genutzten Ebene platziert werden kann |
Das Letzte, was ich vermeiden möchte, ist, packages/ui zu einem Ort für alle Dinge zu machen, die geteilt werden. Wenn browser extension spezifische Umstände und Routing hier eintreten, wird es zu einem Verbindungspunkt und nicht zu einer gemeinsam genutzten Ebene. Wenn das passiert, werden die Vorteile von Monorepo abnehmen.
Hinweise zu apps/wxt
Bei apps/wxt sollten Sie etwas vorsichtig sein. WXT TypeScript-Einstellungen erweitert normalerweise .wxt/tsconfig.json von Roots tsconfig.json. Allerdings nimmt Monorepo möglicherweise nicht diese Form an. In diesem Fall müssen Sie .wxt/wxt.d.ts in Ihr TypeScript-Projekt aufnehmen.
Mit anderen Worten: Obwohl apps/wxt Teil des Monorepo ist, ist es stabiler, es als unabhängiges TypeScript-Projekt zu behandeln.
Verwenden Sie tsconfig.paths nicht als primäres Mittel für grenzüberschreitende Verweise
Das ist ziemlich wichtig.
In den Versionshinweisen zu TypeScript 5.7 (https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-7.html) heißt es eindeutig, dass Importe, die von baseUrl und paths abhängen, bei der Ausgabe von JS nicht umgeschrieben werden können. Mit anderen Worten: Ein Design, das Paketgrenzen überschreitet und nur tsconfig.paths verwendet, besteht möglicherweise die Typprüfung, wird jedoch wahrscheinlich in der Ausführungs- oder Veröffentlichungsphase verzerrt.
Grundsätzlich sollten Sie grenzüberschreitende Verweise im Monorepo in der folgenden Reihenfolge berücksichtigen.
- Separate Pakete
- Abhängigkeiten mit
workspace:verbinden - Bestimmen Sie die öffentliche Seite mit
exportsvonpackage.json - Erstellen Sie einen Abhängigkeitsreihenfolge-Build mit
TypeScript Project References
Es ist weniger wahrscheinlich, dass paths beschädigt wird, wenn es als Hilfsmittel im Paket aufbewahrt wird.
Biome passt gut zu dieser Prämisse
Ich denke, die Entscheidung, ESLint zu entfernen und sich auf Biome zu konzentrieren, ist ganz natürlich. Biomes Leitfaden für große Projekte organisiert auch die Prämisse, Root-Konfiguration und verschachtelte Konfiguration für große Repos wie Monorepo und Workspace unterschiedlich zu verwenden. In v2 wird auch eine auf Monorepo basierende Konfiguration eingeführt.
Bei diesem Maßstab wäre es einfacher, den Lint/das Format an Biome zu senden und sich nur um die Projektgrenze zu kümmern und auf der TypeScript-Seite zu erstellen.
Minimalkonfigurationsbild
Dies reicht für die Ersteinrichtung.
- Platzieren Sie
pnpm-workspace.yamlim Stammverzeichnis - Platzieren Sie
tsconfig.jsonim Lösungsstil im Stammverzeichnis undreferencesin jedem Paket packages/coreundpackages/uiaktivierencomposite- Das freigegebene Paket gibt
exportsvonpackage.jsonan - Platzieren Sie
biome.jsonim Stammverzeichnis - Überprüfen Sie für
apps/wxtseparat, wie mit WXT-Typdefinitionen umgegangen wird.
An diesem Punkt können Sie ziemlich lange kämpfen.
Wann das nächste Werkzeug hinzugefügt werden soll
| Was hinzufügen | Wann soll | hinzugefügt werden?
| --- | --- |
| Turborepo | Build / Test / Lint ist schwer, CI-Optimierung ist erforderlich, ich möchte das Aufgabendiagramm klären |
| Changesets | Ich möchte ein freigegebenes Paket versionieren und veröffentlichen |
| Nx | Ich wollte automatische Generierung, Polyglott und eine stärkere Monorepo-Verwaltung |
| Migration zu bun workspace | Ich wollte Laufzeit/Paketmanager/Test mit Bun | vereinheitlichen
Mit Monorepo funktioniert es besser, nur dort hinzuzufügen, wo der Schmerz auftritt, als alles von Anfang an hinzuzufügen.
Zusammenfassung
Es gibt keine einzelne optimale Lösung für TypeScript-Monorepo. pnpm workspace + Turborepo + TypeScript Project References eignet sich hervorragend für allgemeine, nicht schwierige Antworten. Wenn Docker und Paketveröffentlichung jedoch nach der Aufteilung in apps/web, apps/wxt, packages/ui und packages/core noch nicht zu schwer sind, wäre es leichter und weniger wahrscheinlich, dass es abstürzt, wenn Sie mit pnpm workspace + Biome + TypeScript Project References beginnen.
Wichtig ist nicht, die Anzahl der Tools zu erhöhen, sondern core und ui dünn zu halten und grenzüberschreitende Bezüge mit workspace: und exports ehrlich auszudrücken. Wenn das nicht klappt, ist es noch nicht zu spät, turbo später hinzuzufügen.
hsb.horse