React SPA Monorepo CI/CD: So automatisieren Sie Tests und deployen nur, was sich geändert hat
Die meisten Monorepo-Artikel hören bei der Ordnerstruktur auf. Sie zeigen Ihnen, wie Sie Apps und Packages organisieren, fügen vielleicht eine gemeinsame Konfiguration hinzu und bezeichnen es als erledigt. Aber die Ordnerstruktur ist nicht das, was ein Monorepo produktionsreif macht. Was wirklich zählt, ist, ob Ihre CI/CD-Pipeline erkennen kann, was sich geändert hat, die richtigen Validierungs-Gates ausführt und nur die Apps deployt, die bewegt werden müssen.
Das ist der Unterschied zwischen einem Monorepo, das sauber aussieht, und einem, das zuverlässig ausliefert. Das react-spa-monorepo-cicd-Repository ist genau auf diese Unterscheidung ausgelegt. Es ist eine Referenzarchitektur mit 7 Validierungs-Gates, intelligenter Änderungserkennung, Playwright E2E-Abdeckung, Staging- und Produktions-Branches und automatisiertem Rollback über SSH und rsync. Dieser Artikel erläutert, warum jedes dieser Elemente wichtig ist und wie sie zu einem skalierbaren Release-System zusammenpassen.
Warum CI/CD der eigentliche Wert in einem SPA-Monorepo ist
Ein Monorepo allein reduziert kein Deployment-Risiko. Drei Apps in ein Repository zu packen, ohne gemeinsame Automatisierung, ist nur ein gemeinsamer Ordner mit zusätzlichen Merge-Konflikten. Der tatsächliche Nutzen entsteht durch konsistente Validierung, gemeinsame Automatisierung und selektives Deployment — nichts davon passiert automatisch, nur weil Ihre Apps eine gemeinsame package.json-Root teilen.
Die Pipeline ist wichtiger als der Ordnerbaum. Ein Monorepo mit starkem CI/CD gibt jeder App die gleichen Validierungsstandards, den gleichen Deployment-Pfad und den gleichen Rollback-Prozess. Ein Monorepo ohne CI/CD gibt Ihnen drei Apps, die schwieriger unabhängig zu releasen sind, als wenn sie in separaten Repositories lägen.
Deshalb ist das react-spa-monorepo-cicd-Repo als Referenzarchitektur für mehrere Apps mit automatisiertem Deployment und vollständiger CI/CD-Validierung positioniert, nicht nur als Starter-Template. Der Wert liegt im Release-System, nicht im Workspace-Layout.
Wie die Pipeline von Pull Request bis Produktion funktioniert
Der Release-Pfad folgt einem linearen Promotionsmodell mit Validierung bei jedem Schritt:
- Pull Request öffnen — CI erkennt, welche Bereiche sich geändert haben, und führt die vollständige Validierungssuite aus
- In Staging mergen — die gleichen Prüfungen laufen erneut gegen das Merge-Ergebnis, dann werden betroffene Apps in die Staging-Umgebung deployt
- Staging verifizieren — manuelle oder automatisierte Smoke-Tests bestätigen, dass das Deploy gesund ist
- Staging in Main mergen — Validierung läuft erneut, und betroffene Apps werden in die Produktion deployt
- Post-Deploy-Health-Checks — die Pipeline bestätigt, dass jede deployte App korrekt antwortet
Tests laufen absichtlich nach dem Merge erneut. Ein Pull Request validiert den Branch isoliert, aber der gemergte Zustand kann sich durch Konflikte oder gleichzeitige Änderungen unterscheiden. Post-Merge-Validierung stellt sicher, dass der exakt gemergte Code noch jedes Gate besteht, bevor etwas deployt wird.
Das ist sicherer als direkt von Feature-Branches zu deployen, weil jedes Produktions-Deploy mindestens dreimal validiert wurde: beim PR, nach dem Merge in Staging und nach dem Merge in Main. Jede Validierung fängt eine andere Kategorie von Problemen ab.
Die sieben Validierungs-Gates, die jedes Deploy schützen
Die Pipeline erzwingt sieben Kategorien von Prüfungen, bevor ein Deployment stattfindet, geordnet vom günstigsten zum teuersten:
- Format-Check — Prettier erkennt Stil-Inkonsistenzen in Sekunden
- Lint — ESLint markiert Code-Qualitätsprobleme und potenzielle Bugs
- Type-Check — Der TypeScript-Compiler verifiziert Korrektheit über alle Packages hinweg
- Unit-Tests — Vitest führt schnelle, isolierte Tests für Komponenten und Utilities aus
- Build — Vite kompiliert jede App zu produktionsreifen statischen Assets
- Security-Audit — Abhängigkeits-Scanning markiert bekannte Schwachstellen
- E2E-Tests — Playwright führt Browser-Level-Tests gegen die gebauten Apps aus
Die Reihenfolge ist bewusst gewählt. Format- und Lint-Checks kosten fast nichts in der Ausführung. Wenn sie fehlschlagen, gibt es keinen Grund, Zeit mit dem Build von drei Apps und dem Start eines Docker-Stacks für E2E zu verbringen. Scheitern Sie früh bei günstigen Checks, damit Sie nur Ressourcen für teure Checks aufwenden, wenn die Grundlagen bereits sauber sind.
Das ist das gleiche Fast-Fail-Prinzip, das jede CI-Pipeline effizient macht. Der Unterschied ist, dass dieses Repo es konsistent über ein Monorepo mit mehreren deploybaren Apps anwendet, was bedeutet, dass die Kosteneinsparungen sich vervielfachen. Wenn ein Lint-Fehler in der Admin-SPA die Pipeline in 15 Sekunden fehlschlagen lässt, vermeiden Sie Minuten unnötiger Builds, Security-Scans und Browser-Tests für beide SPAs und die Hauptseite.
Warum selektive Deploys der größte Monorepo-Vorteil sind
Ohne Änderungserkennung baut und deployt jeder Push jede App neu. Das verschwendet Rechenleistung, verlangsamt Feedback und vergrößert den Blast-Radius jedes Releases. Ein Bug in der Admin-SPA sollte kein Re-Deployment der Portal-SPA und der Marketing-Seite erfordern.
Das Repository nutzt intelligente Änderungserkennung, um Dateiänderungen auf Deploy-Ziele abzubilden:
- Änderungen in
apps/admin-spa/deployen nur die Admin-SPA - Änderungen in
apps/portal-spa/deployen nur die Portal-SPA - Änderungen in
apps/main-site/deployen nur die Hauptseite (eine statische HTML-Seite, keine React SPA) - Änderungen in
packages/lösen beide SPA-Deploys aus, weil gemeinsamer Code beide Consumer betreffen könnte - Änderungen an Docs oder Markdown überspringen das Deployment vollständig
Das beeinflusst direkt drei Dinge, die Teams wichtig sind: CI-Kosten, Feedback-Geschwindigkeit und Release-Risiko. Eine App statt drei zu bauen und zu deployen reduziert die Rechenzeit entsprechend. Eine gezielte Pipeline wird schneller fertig, was schnellere Code-Review-Zyklen bedeutet. Und nur die geänderte App zu deployen reduziert die Angriffsfläche für Regressionen in nicht verwandtem Code.
Selektives Deployment ist der Punkt, an dem Monorepos ihren Wert beweisen. Ohne es werden Monorepos schnell langsam und teuer, wenn die Anzahl der Apps wächst. Mit selektivem Deployment verlangsamt das Hinzufügen einer neuen App zum Repository nicht die Deployments für jede andere App.
Wo Playwright in einen seriösen Frontend-Release-Prozess passt
E2E-Tests sind die letzte Vertrauensschicht vor dem Deploy. Sie validieren deploybares Verhalten in einer produktionsähnlichen Umgebung, was sich grundlegend von Unit-Tests unterscheidet, die gegen isolierte Komponenten laufen.
Das Repository führt Playwright-Tests gegen gebaute Artefakte aus, die von Docker und nginx bereitgestellt werden, nicht gegen einen Dev-Server. Diese Unterscheidung ist wichtig, weil Dev-Server Hot Module Replacement verwenden, Optimierungen überspringen und Assets anders ausliefern. E2E gegen Produktions-Build-Output auszuführen fängt Probleme ab, die nur unter realen Deployment-Bedingungen auftreten.
Die E2E-Suite deckt ab:
- App-Laden — jede SPA rendert ihre Root-Komponente
- Route-Boundaries — Client-seitiges Routing funktioniert innerhalb jeder App
- Cross-App-Navigation — Links zwischen SPAs werden ohne Fehler aufgelöst
- Visuelle Regression — Screenshots werden mit Baselines verglichen, um unbeabsichtigte UI-Änderungen zu erkennen
- Accessibility — axe-core-Checks markieren kritische Verstöße vor dem Deploy
Das ist Vertrauen auf Pipeline-Ebene, nicht Debugging auf Entwicklerebene. E2E-Tests sollten Unit-Tests nicht ersetzen. Sie sollten eine andere Frage beantworten: „Funktioniert das gebaute Artefakt korrekt, wenn es so ausgeliefert wird, wie es die Produktion tun wird?” Wenn die Antwort Nein lautet, findet das Deploy nicht statt.
Warum sich Staging und Produktion unterschiedlich verhalten sollten
Das Repository trennt Umgebungen nach Branch. Pushes auf staging bauen im Staging-Modus, verwenden Staging-Secrets und deployen auf den Staging-Server. Pushes auf main bauen im Produktionsmodus, verwenden Produktions-Secrets und deployen auf den Produktionsserver. Kein Anwendungscode ändert sich zwischen den Umgebungen — nur der Build-Modus, die Secrets und das Deploy-Ziel unterscheiden sich.
Staging ist keine Demo-Umgebung. Es ist eine Vertrauensschicht. Der Zweck von Staging ist es, Probleme zu erkennen, die nur in einer deployen Umgebung auftreten — falsche Umgebungsvariablen, fehlerhafte Server-Konfiguration, veraltete Assets — bevor diese Probleme die Kunden erreichen.
Produktions-Deploys können eine manuelle Genehmigung durch GitHub Environment Protection Rules erfordern. Nachdem die Validierung bestanden ist, pausiert der Deploy-Job und wartet auf die Freigabe durch ein autorisiertes Teammitglied. Das ist kontrollierte Automatisierung: Die Pipeline übernimmt die Mechanik, Menschen übernehmen die Bewertung. Vollautomatisch muss nicht vollständig unüberprüft bedeuten.
Das Deployment-Modell: rsync, Backups und Rollback
Das Repository deployt mit rsync über SSH. Jede App hat ihren eigenen Zielpfad auf dem Server, sodass das Deployen der Admin-SPA nicht riskiert, die Dateien der Portal-SPA zu überschreiben. Die Deploy-Skripte unterstützen einen Dry-Run-Modus, damit Sie die Absicht überprüfen können, bevor Dateien übertragen werden.
Vor jedem Deployment erstellt die Pipeline ein Backup mit Zeitstempel der aktuellen Version. Wenn ein Deploy ein Problem einführt, ist ein Rollback ein einzelner Befehl, der das letzte Backup wiederherstellt. Das ist kein nachträglicher Notfall-Gedanke — es ist Teil des Delivery-Designs.
Post-Deploy-Health-Checks schließen den Kreis. Eine erfolgreiche Dateiübertragung garantiert keine funktionierende App. Die Server-Konfiguration könnte falsch sein, Umgebungsvariablen könnten fehlen oder der Build könnte im falschen Modus erstellt worden sein. Health-Checks bestätigen, dass die deployte App tatsächlich antwortet, und wenn sie fehlschlagen, meldet die Pipeline einen Fehler, obwohl das Deploy selbst erfolgreich war.
Einfache Deployment-Mechanismen sind oft wartbarer als überkomplexe Plattformen. Rsync, SSH und Backups mit Zeitstempel sind langweilige Technologien, aber sie sind vorhersagbar, debugbar und jedem Ops-Ingenieur im Team bekannt.
Wenn Sie auch darüber nachdenken, was durch Ihre Pipeline fließt, abzusichern, lesen Sie Software-Lieferkettensicherheit im KI-Zeitalter für Strategien zur Abhängigkeitsintegrität und SBOMs sowie Absicherung von KI-Coding-Agent-Workflows für Sandboxing und Review-Gates, wenn KI-generierter Code in Monorepo-Pull-Requests einfließt.
GitHub Actions und GitLab CI im selben Monorepo
Das Repository enthält sowohl .github/workflows/validate-and-deploy.yml als auch .gitlab-ci.yml mit Setup-Dokumentation für beide. Die Unterstützung beider ist nützlich für Teams, die zwischen Plattformen migrieren, verschiedene Kunden bedienen oder evaluieren, welches CI-System besser zu ihrem Workflow passt.
Der wichtigere Punkt ist, dass das CI/CD-Muster wichtiger ist als der Anbieter. Die gleiche Validierungsleiter, die gleiche selektive Deploy-Logik und das gleiche branch-basierte Umgebungsmodell funktionieren in beiden Systemen. Die Implementierungssyntax unterscheidet sich, aber die Architektur ist portabel. Wenn Sie das Muster verstehen, können Sie es in jedem CI-System implementieren.
Was Teams beim Monorepo-CI/CD typischerweise falsch machen
Die häufigsten Fehler sind keine technischen Ausfälle. Es sind architektonische Versäumnisse:
- Die Ordnerstruktur als gesamte Lösung behandeln. Ein sauberer Workspace schützt Sie nicht vor fehlerhaften Merges oder verschwendeten CI-Minuten.
- Änderungserkennung überspringen. Ohne sie baut jeder Push alles neu, was den Geschwindigkeitsvorteil eines Monorepos eliminiert.
- E2E zu früh oder zu spät ausführen. E2E vor dem Build verschwendet Zeit mit Tests, die nicht laufen können. E2E nach dem Deploy bedeutet, dass Fehler eine Umgebung erreichen, bevor sie erkannt werden.
- Alles bei jedem Merge deployen. Das macht jedes Release zu einem Full-Stack-Event, unabhängig davon, was sich tatsächlich geändert hat.
- Keinen Rollback-Plan haben. Wenn Ihre einzige Wiederherstellungsoption „einen Fix nach vorn pushen” ist, sind Sie ein schlechtes Deploy von längeren Ausfallzeiten entfernt.
- Staging- und Produktionsverhalten vermischen. Wenn Staging automatisch deployt, Produktion aber ebenfalls automatisch deployt, stellt Staging tatsächlich kein Gate dar.
Die meisten dieser Probleme werden gelöst, indem die Pipeline bewusst designed wird, anstatt sie organisch wachsen zu lassen. Das react-spa-monorepo-cicd-Repo existiert genau dafür, zu demonstrieren, wie eine bewusst gestaltete Pipeline aussieht.
Für wen dieses Setup am besten geeignet ist
Diese Architektur passt zu Teams, die mehrere SPAs oder eine Mischung aus statischen und SPA-Apps aus einem Repository betreiben. Das umfasst:
- Produktteams, die separate kundenseitige Apps verwalten, die Design-Systeme oder API-Clients teilen
- Agenturen, die mehrere Frontend-Oberflächen für Kunden erstellen und pflegen
- Interne Plattformteams mit gemeinsamen Packages, die von mehreren Apps genutzt werden
- Entwickler, die einfaches, aber produktionstaugliches CI/CD ohne ein schwergewichtiges Monorepo-Framework wollen
Wenn Sie bereits Nx oder Turborepo nutzen und mit der Komplexität zufrieden sind, mag dieser Ansatz zu manuell wirken. Aber wenn Sie verstehen wollen, was diese Tools abstrahieren, oder wenn Sie eine leichtgewichtigere Alternative wollen, die Sie vollständig kontrollieren, ist dies ein starker Ausgangspunkt.
Nächste Schritte
Wenn Sie diese Pipeline hands-on implementieren möchten, folgen Sie dem begleitenden Tutorial: So richten Sie CI/CD und automatisierte Tests für ein React SPA Monorepo ein. Es führt Sie durch jeden Schritt, vom Klonen des Repos über die Konfiguration der Validierungs-Gates, das Ausführen von Playwright E2E-Tests, das Einrichten selektiver Deploys bis hin zur Konfiguration von Staging- und Produktions-Releases.
Für Teams, die bereits CI/CD-Pipelines betreiben, empfiehlt es sich, die Muster in diesem Artikel auf Ihr bestehendes Setup abzubilden:
- Fügen Sie Änderungserkennung hinzu, wenn Sie bei jedem Push alles neu bauen
- Ordnen Sie Ihre Validierungs-Gates vom günstigsten zum teuersten
- Trennen Sie Staging von Produktion mit branch-basierten Umgebungsregeln
- Fügen Sie Post-Deploy-Health-Checks hinzu, damit eine erfolgreiche Übertragung nicht das Ende der Geschichte ist
- Integrieren Sie Rollback in die Pipeline, anstatt es als Notfallverfahren zu behandeln
Wenn Sie einen Ausgangspunkt statt eines leeren Architektur-Dokuments wollen, bietet Ihnen dieses Repo einen: ein Monorepo-Release-System mit Validierungs-Gates, selektivem Deployment, E2E-Tests und bereits eingebautem Rollback. Der nächste Schritt ist, diese Muster an Ihre eigenen Apps und Deployment-Ziele anzupassen, anstatt CI/CD von Grund auf neu zu erfinden.
Zum react-spa-monorepo-cicd Repo →
Zum Schritt-für-Schritt-Tutorial →
Häufig gestellte Fragen
Was ist der Unterschied zwischen einem Monorepo und einem Polyrepo für CI/CD?
Ein Monorepo hält mehrere Apps und gemeinsame Packages in einem Repository, was gemeinsame CI/CD-Pipelines, konsistente Validierung und selektives Deployment basierend auf Änderungserkennung ermöglicht. Ein Polyrepo verwendet separate Repositories pro App, was Pipelines pro App vereinfacht, aber mehr Koordination für gemeinsame Abhängigkeiten und Cross-App-Tests erfordert.
Wie funktioniert selektives Deployment in einem Monorepo?
Selektives Deployment nutzt Änderungserkennung, um modifizierte Dateien auf Deploy-Ziele abzubilden. Wenn sich nur das Verzeichnis einer App geändert hat, wird nur diese App gebaut und deployt. Änderungen an gemeinsamen Packages lösen Deploys für alle Apps aus, die von ihnen abhängen. Das reduziert CI-Kosten, beschleunigt Feedback und begrenzt den Blast-Radius jedes Releases.
Sollten E2E-Tests vor oder nach dem Deployment laufen?
E2E-Tests sollten vor dem Deployment laufen, gegen gebaute Artefakte in einer produktionsähnlichen Umgebung. Das fängt Integrations- und Deployment-Probleme ab, bevor sie Staging oder Produktion erreichen. Post-Deploy-Health-Checks bestätigen dann, dass die tatsächlich deployte App korrekt antwortet.
Kann ich dieses CI/CD-Muster mit Nx oder Turborepo verwenden?
Ja. Die Validierungsleiter, die selektive Deploy-Logik und das branch-basierte Umgebungsmodell sind Architekturmuster, keine toolspezifischen Konfigurationen. Wenn Sie bereits Nx oder Turborepo für Task-Orchestrierung und Caching verwenden, können Sie diese CI/CD-Muster darüber legen. Das react-spa-monorepo-cicd-Repo demonstriert die Muster ohne ein schwergewichtiges Framework, damit Sie genau sehen können, was diese Tools abstrahieren.
Wie füge ich eine neue App zur Monorepo-Pipeline hinzu?
Erstellen Sie die App unter apps/, fügen Sie ihr Verzeichnis zum Änderungserkennungs-Skript (scripts/changed-files.sh) hinzu und verdrahten Sie entsprechende Build-, Deploy- und E2E-Ziele im CI-Workflow. Das selektive Deploy-Modell skaliert linear — jede neue App bekommt ihren eigenen bedingten Pfad, ohne Deploys für bestehende Apps zu verlangsamen.
Wie behandelt dieser Ansatz Änderungen an gemeinsamen Packages?
Änderungen unter packages/ lösen Rebuilds und Deploys für alle Apps aus, die von diesen gemeinsamen Packages abhängen. Das ist beabsichtigt — ein Bug in gemeinsam genutztem Code könnte jeden Consumer betreffen, daher muss jede abhängige App neu gebaut, erneut getestet und re-deployt werden, um Regressionen zu erkennen.