logo hsb.horse
← Zur Blog-Übersicht

Blog

TypeScript Monorepo Organisieren der optimalen Lösung, Ausgabe 2026

Wir haben die Rollen von pnpm workspace, Turborepo, TypeScript Project References, Biome und WXT organisiert und die allgemeine einfache Lösung und die praktische Lösung mit einer 4-Paket-Struktur zusammengefasst.

Veröffentlicht:

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.

  1. Sichere Konfiguration beim Erstellen eines neuen TypeScript-Monorepos
  2. Realistische Konfiguration basierend auf den spezifischen Annahmen von apps/web, apps/wxt, packages/ui, packages/core

Zuerst das Fazit

VoraussetzungenErste Konfiguration zur AuswahlErgänzung
Neues generisches Monorepo. Zukünftig werden Paketfreigabe, CI-Optimierung und Docker-Integration berücksichtigtpnpm workspace + Turborepo + TypeScript Project References + package.json von exports + ChangesetsDas stabilste
4 Paketkonfigurationen: apps/web, apps/wxt, packages/ui, packages/core. Ich verwende kein Docker. Veröffentlichen Sie keine freigegebenen Pakete auf npmpnpm workspace + Biome + TypeScript Project ReferencesTurborepo wird zu diesem Zeitpunkt nicht benötigt
Bun stellt die Ausführungsumgebung, den Paketmanager und Tests bereit bun workspace ist ebenfalls ein KandidatAllerdings 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.

RolleEmpfehlung
Arbeitsbereichsverwaltungpnpm workspace
Typgrenzen und inkrementelle BuildsTypeScript Project References
Aufgabenausführung, Parallelisierung und CachingTurborepo
öffentliches Gesicht der Paketgrenzeexports von package.json
Versionierung / ÄnderungsprotokollChangesets
Fussel / FormatBiome 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/core
packages/ui -> packages/core
apps/web -> packages/ui, packages/core
apps/wxt -> packages/ui, packages/core

Wenn 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.

SchmerzWarum Turborepo funktioniert
Die gesamte Build-/Test-/Lint-Zeit ist langCaching und parallele Ausführung sind wirksam
Ich möchte die Abhängigkeitsreihenfolge von Aufgaben klärendependsOn kann einen Graphen
Ich möchte CIbeschleunigen Remote-Cache funktioniert
Ich möchte nur die notwendigen Pakete für Dockerextrahieren 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.

PfadDinge zum VerstauenDinge, die Sie nicht sagen sollten
packages/coreDomäne, Schema, Validierung, API-Client, reine Funktion, ZustandsmodellBenutzeroberfläche, Routing, Browser-API
packages/uiUmgebungsunabhängige React-Komponente/HookWXT-spezifische Verarbeitung, Router, Erweiterungsspeicher
apps/webZusammenstellung als Webanwendung, Seite, Routing, Adaptererweiterungsspezifische Umstände
apps/wxtHintergrund-/Inhaltsskript, Browser-API, WXT-spezifische EinstellungenWebspezifisches 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.

  1. Separate Pakete
  2. Abhängigkeiten mit workspace: verbinden
  3. Bestimmen Sie die öffentliche Seite mit exports von package.json
  4. 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.

  1. Platzieren Sie pnpm-workspace.yaml im Stammverzeichnis
  2. Platzieren Sie tsconfig.json im Lösungsstil im Stammverzeichnis und references in jedem Paket
  3. packages/core und packages/ui aktivieren composite
  4. Das freigegebene Paket gibt exports von package.json an
  5. Platzieren Sie biome.json im Stammverzeichnis
  6. Überprüfen Sie für apps/wxt separat, 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.

Referenz