Mehrere Major-Versionen eines Frameworks
Mehrere Major-Versionen eines Frameworks parallel zu betreiben ist technisch möglich. Als dauerhafte Zielarchitektur ist es jedoch meist weder wirtschaftlich noch architektonisch sinnvoll.
Ohne starke Isolation teilen mehrere Framework-Runtimes weiterhin denselben Browserkontext. Mit vollständiger Isolation werden statt nahtlos komponierter Microfrontends eigenständige Anwendungen ineinander integriert.
Genau diese Isolation kann dennoch berechtigt sein: als zeitlich begrenzte Grenze um eine aus nachvollziehbaren Gründen alte Anwendung, die nicht sicher auf einmal migriert werden kann. Dann ist sie eine Migrationsbrücke. Sie ist ausdrücklich nicht das Zielbild.
Technisch machbar, als Dauerzustand nicht sinnvoll
Abschnitt betitelt „Technisch machbar, als Dauerzustand nicht sinnvoll“Ein häufig genanntes Versprechen von Microfrontends lautet: Jedes Remote kann seine eigene Framework-Version verwenden.
Das Versprechen ist nicht falsch. Ein Integrationsmodell kann Anwendungen laden, die mit unterschiedlichen Major-Versionen desselben Frameworks gebaut wurden. Daraus folgt jedoch noch keine tragfähige Architektur. Die Aussage beantwortet zunächst nur, ob sich die Artefakte irgendwie gemeinsam ausführen lassen.
Sie beantwortet nicht, wie viele Framework-Runtimes der Browser laden und initialisieren muss. Sie sagt nichts darüber, welche globalen Ressourcen diese Runtimes weiterhin teilen, wie kompatible Versionen aufgelöst werden, wie groß die unterstützte Testmatrix wird oder wie lange der Versionsmix bestehen soll. Vor allem benennt sie keinen Verantwortlichen für die Rückführung.
Technische Machbarkeit beantwortet die Frage, ob etwas ausgeführt werden kann. Architektur muss zusätzlich beantworten, ob es dauerhaft betrieben werden sollte.
Nehmen wir ein bewusst überzeichnetes Beispiel:
Host└── Angular 22
Remote A└── Angular 17
Remote B└── Angular 19Die Versionsnummern sind nur Platzhalter für deutlich auseinanderliegende Framework-Generationen. Entscheidend ist nicht, ob genau diese Kombination funktioniert. Entscheidend ist, was eine Integrationsplattform leisten muss, wenn die Anwendungen keine verlässlich gemeinsame Framework-Version verwenden können.
Drei Major-Versionen sind mehr als drei Versionsnummern
Abschnitt betitelt „Drei Major-Versionen sind mehr als drei Versionsnummern“Werden die Framework-Abhängigkeiten nicht gemeinsam bereitgestellt, bringt jede Anwendung im ungünstigsten Fall ihre eigene Runtime mit:
Browser├── Host│ └── Angular-22-Runtime├── Remote A│ └── Angular-17-Runtime└── Remote B └── Angular-19-RuntimeDann existiert nicht lediglich dieselbe Versionsnummer an drei Stellen in einer Lockdatei. Mehrfach vorhanden sein können Framework-Code, Bootstrap-Logik, Dependency-Injection-Strukturen, Rendering-Infrastruktur, Reaktivitäts- oder Change-Detection-Mechanismen, Router- und HTTP-Infrastruktur sowie frameworknahe Bibliotheken. Hinzu kommen eigene Komponenten- und Anwendungsbäume, interne Datenstrukturen, Subscriptions, Metadaten und Lebenszyklen.
Drei Major-Versionen können im schlechtesten Fall drei Framework-Runtimes bedeuten.
Das heißt nicht, dass sich jede übertragene Datei oder jedes Byte exakt verdreifacht. Tree Shaking, Lazy Loading, Browser-Caching und unterschiedlich zugeschnittene Bundles verändern die tatsächlichen Kosten. Manche technische Abhängigkeit kann weiterhin gemeinsam genutzt werden. Ein Remote wird möglicherweise erst geladen, wenn der Nutzer den zugehörigen Bereich öffnet.
Diese Einschränkungen ändern jedoch nichts am Grundproblem. Unterschiedliche Runtime-Versionen müssen heruntergeladen, geparst, ausgeführt und initialisiert werden. Sie benötigen Speicher und erzeugen eigene interne Strukturen. Ihr Bootstrap beansprucht Main-Thread-Zeit. Auch ein bereits im Browser-Cache vorhandenes Bundle muss weiterhin ausgeführt werden und belegt nach der Initialisierung Speicher.
Der Browser-Cache kann erneute Downloads reduzieren. Er beseitigt weder die Ausführung noch den Speicherbedarf mehrerer unterschiedlicher Runtimes.
Der Nutzer bezahlt die Versionsfreiheit
Abschnitt betitelt „Der Nutzer bezahlt die Versionsfreiheit“Aus Sicht der Teams wirkt die Situation zunächst komfortabel:
Team A bleibt auf Major 17Team B verwendet Major 19Team C migriert auf Major 22Jedes Team kann lokal entscheiden. Keine gemeinsame Migration blockiert die nächste fachliche Änderung. Die organisatorische Abhängigkeit scheint verschwunden.
Im Browser sieht dieselbe Entscheidung anders aus:
Nutzer└── lädt und betreibt mehrere Framework-GenerationenDie Teams vermeiden einen Teil der gemeinsamen Koordination. Der Nutzer trägt dafür zusätzliche Laufzeitkosten.
Die Verschiebung endet nicht bei Downloadgröße und Startzeit. Mehrere Versionen vergrößern die Zahl der Laufzeitkombinationen, die Plattform und Produktteams verstehen und testen müssen. Sie bringen unterschiedliche Toolchains, Library-Kompatibilitäten, Browserannahmen und Wartungszyklen mit. Fehler treten möglicherweise nur in einer bestimmten Kombination aus Host, Remote und gemeinsam genutzter Infrastruktur auf. Monitoring und Support müssen erkennen können, welche Runtime an welcher Stelle beteiligt war.
Auch Sicherheits- und Wartungsverantwortung vervielfachen sich. Eine alte Version bleibt nicht deshalb betreibbar, weil sie hinter einer Remote-Grenze liegt. Irgendjemand muss ihre Abhängigkeiten, bekannten Einschränkungen, Build-Werkzeuge und Betriebsannahmen weiterhin beherrschen.
Was für ein einzelnes Team lokal bequem erscheint, kann systemweit teuer werden. Unabhängige Versionswahl beseitigt Koordination nicht. Sie verschiebt einen Teil ihrer Kosten in den Browser, die Integrationsplattform und die langfristige Wartung.
Shared Dependencies sind ein Versionsvertrag
Abschnitt betitelt „Shared Dependencies sind ein Versionsvertrag“Die offensichtliche Alternative besteht darin, die Framework-Runtime gemeinsam bereitzustellen:
Host und Remotes │ └── gemeinsame Framework-RuntimeEine gemeinsame Runtime kann duplizierte Framework-Bundles vermeiden, Bootstrap-Aufwand reduzieren und frameworknahe Verträge konsistent halten. Host und Remotes bewegen sich dann innerhalb derselben Laufzeitumgebung und können enger komponiert werden.
Dafür müssen sie mit der tatsächlich bereitgestellten Version kompatibel sein.
Shared Dependencies sparen Laufzeitkosten, erzeugen aber einen gemeinsamen Versionsvertrag.
Dieser Vertrag ist keine technische Nebensächlichkeit. Sobald eine Framework-Abhängigkeit als Singleton oder vergleichbar zentrale Runtime behandelt wird, kann ein Team seine Major-Version nicht mehr vollständig isoliert wählen. Eine Migration muss abgestimmt, geprüft und innerhalb des vereinbarten Korridors durchgeführt werden. Updates können mehrere Anwendungen betreffen, selbst wenn deren fachliche Releases unabhängig bleiben.
Die Alternative sind getrennte Runtimes. Sie erlauben größere technische Versionsfreiheit und können eine schrittweise Migration ermöglichen. Dafür steigen Runtime-Aufwand, Testbedarf und Integrationskomplexität.
Der Trade-off lässt sich nicht wegkonfigurieren: Entweder teilen Anwendungen eine Runtime und akzeptieren einen Versionsvertrag. Oder sie betreiben getrennte Runtimes und bezahlen deren technische und organisatorische Kosten.
Getrennte Runtimes sind kein getrennter Browser
Abschnitt betitelt „Getrennte Runtimes sind kein getrennter Browser“Getrennte Bundles erwecken leicht den Eindruck, die Anwendungen seien vollständig voneinander isoliert. Tatsächlich laufen sie bei einer normalen Komposition weiterhin im selben Dokument.
Sie teilen sich dasselbe window, dasselbe document und denselben Main Thread. Sie greifen auf dieselbe Browser-History und dieselben globalen APIs zu. Auch DOM, CSS-Kaskade, globale Styles, CSS Custom Properties, Overlay-Flächen unter body, localStorage, globale Error Handler, Telemetrieinstrumentierungen und die Custom-Element-Registry können gemeinsame Konfliktflächen bilden. Je nach Auslieferung und Geltungsbereich gilt das auch für Service Worker sowie globale Polyfills oder Patches.
Bundle-Isolation ist keine Ressourcen-Isolation. Der Browser kennt keine Teamgrenzen.
Daraus folgt nicht, dass mehrere Runtimes zwangsläufig kollidieren. Gut gekapselte Anwendungen können lange stabil nebeneinander laufen. Je größer der Versionsabstand und je mehr globale Mechanismen beteiligt sind, desto mehr Annahmen müssen jedoch geprüft und dauerhaft abgesichert werden.
Ein Router kann die Kontrolle über URL und History beanspruchen. Globale Reset-Styles können über den sichtbaren Root eines Remotes hinauswirken. Ein Overlay kann außerhalb des Komponentenbaums unter body erscheinen. Globale Registrierungen benötigen eindeutige Namen. Unterschiedliche Error Handler und Telemetrieinstrumentierungen beobachten denselben Prozess. Ein rechenintensives Remote blockiert denselben Main Thread wie der Host.
Auch getrennte Framework-Runtimes konkurrieren damit weiterhin um gemeinsam genutzte Ressourcen. Die Runtime-Grenze schützt nicht vor CPU-Auslastung, Speicherverbrauch oder globalen Seiteneffekten im Dokument.

Der harte Grenzfall: vollständige Isolation im iframe
Abschnitt betitelt „Der harte Grenzfall: vollständige Isolation im iframe“Wenn die gegenseitigen Laufzeitannahmen nicht mehr zuverlässig kontrollierbar sind, bleibt als konsequente technische Grenze ein eigener Browserkontext:
Host-Anwendung└── iframe └── vollständige Legacy-Anwendung ├── eigenes window ├── eigenes document ├── eigene Framework-Runtime ├── eigener Router ├── eigene Styles └── eigener LebenszyklusEin iframe trennt deutlich stärker als ein weiteres Bundle im selben Dokument. Die eingebettete Anwendung besitzt eigene JavaScript-Globals, ein eigenes DOM, eine eigene CSS-Struktur und eine eigene Router-Infrastruktur. Globale JavaScript-Patches oder Registrierungen wirken nicht automatisch im window des Hosts. Stark auseinanderliegende Framework-Generationen lassen sich damit technisch verlässlicher voneinander abgrenzen.
Diese Isolation ist real. Sie ist aber nicht kostenlos.
Navigation und Browser-History müssen über die Dokumentgrenze koordiniert werden. Authentifizierung und fachlicher Kontext müssen kontrolliert übergeben werden. Fokussteuerung, Tastaturnavigation und Barrierefreiheit benötigen besondere Aufmerksamkeit. Responsive Größenanpassung wird zur Abstimmung zwischen Host und eingebettetem Dokument. Modale Dialoge und Overlays bleiben innerhalb des iframes, selbst wenn das gemeinsame Nutzererlebnis etwas anderes erwarten lässt.
Auch Ladezustände, Fehler und Telemetrie müssen über die Grenze sichtbar gemacht werden. Styling und Nutzerführung lassen sich nur mit zusätzlicher Arbeit vereinheitlichen. Jede notwendige Kommunikation wird zu einem expliziten Nachrichtenvertrag.
Ein iframe kauft starke Isolation mit hohen Integrationskosten.
Vollständige Isolation verändert die Architektur
Abschnitt betitelt „Vollständige Isolation verändert die Architektur“Eine typische Microfrontend-Architektur will fachliche Bereiche innerhalb einer gemeinsam komponierten Oberfläche integrieren:
Gemeinsamer Host├── gemeinsam komponierte Oberfläche├── konsistente Navigation├── gemeinsame Plattformdienste├── integrierte Nutzerführung└── unabhängig veränderbare FachbereicheDer vollständig isolierte Grenzfall sieht anders aus:
Host-Anwendung└── eingebettete eigenständige AnwendungDamit bleiben wichtige Vorteile erhalten. Die eingebettete Anwendung kann unabhängig deployt werden. Sie besitzt einen getrennten technischen Lebenszyklus und eine klare Fehlergrenze. Ein Legacy-Bestand kann weiter betrieben und schrittweise verkleinert werden.
Andere Vorteile werden geschwächt oder teuer erkauft. Nahtlose Komposition, durchgängige Navigation, einheitliches Layout, gemeinsame Plattformmechanismen, integrierte Overlays, konsistente Barrierefreiheit und zentrale Beobachtbarkeit sind nicht mehr selbstverständlich. Der Host integriert nicht mehr nur einen fachlichen Ausschnitt. Er integriert eine vollständige Anwendung mit eigenem Browserkontext.
Je stärker verschiedene Framework-Versionen isoliert werden müssen, desto mehr verschiebt sich die Architektur von gemeinsam komponierten Microfrontends zur Integration vollständiger Anwendungen.
Es ist wenig hilfreich, darüber zu streiten, ob das Ergebnis begrifflich noch ein Microfrontend ist. Die wichtigere Frage lautet: Welchen architektonischen Nutzen wollten wir mit Microfrontends erreichen – und wie viel davon bleibt nach der notwendigen Isolation noch übrig?
Vollständige Isolation ist möglich. Sie wird jedoch erreicht, indem man sich von der eigentlich gewünschten Microfrontend-Komposition entfernt.

Die vermiedene Migration verschwindet nicht
Abschnitt betitelt „Die vermiedene Migration verschwindet nicht“Als dauerhafter Zustand kann ein großer Versionsmix mehrere Framework-Runtimes, steigenden Speicherbedarf, eine wachsende Kompatibilitätsmatrix und verschiedene Toolchains bedeuten. Plattformtests müssen mehr Kombinationen abdecken. Debugging erfordert Wissen über mehrere Framework-Generationen. Sicherheits- und Wartungszyklen laufen auseinander. Im Extremfall wird die Oberfläche aus vollständigen Anwendungen zusammengesetzt, deren Integration dauerhaft eigene Infrastruktur benötigt.
Eine Architektur ist nicht deshalb wirtschaftlich, weil jedes Team seine lokale Migration vermeiden kann.
Die vermiedene Framework-Migration eines Teams kann über Jahre mit zusätzlicher Laufzeit-, Integrations- und Betriebsarbeit bezahlt werden. Ein vermeintlich unabhängiges Release spart kurzfristig Koordination, während Plattform, Support und Nutzer die Folgekosten tragen.
Diese Betrachtung ist keine pauschale Verbotsregel. Es kann sinnvoll sein, eine Migration zeitlich zu entkoppeln. Die Kosten müssen dann jedoch als Investition in einen Übergang verstanden werden. Ohne Zielbild wird aus derselben Investition ein dauerhafter Betriebsaufwand.
Die technische Freiheit eines Teams wird nicht kostenlos. Ihre Kosten erscheinen an anderer Stelle im Gesamtsystem.
Der legitime Ausnahmefall: kontrollierte Migration
Abschnitt betitelt „Der legitime Ausnahmefall: kontrollierte Migration“Eine Anwendung verbleibt selten ohne Grund auf einer deutlich älteren Framework-Version. Große fachliche Reichweite, viele Teams, unzureichende Testautomatisierung, inkompatible Drittbibliotheken, eigene Build-Mechanismen, starke technische Kopplung und kritische Geschäftsprozesse können eine direkte Migration unverantwortlich machen. Häufig müssten mehrere technische Grundlagen gleichzeitig verändert werden, während die verfügbare Kapazität begrenzt ist.
Die Forderung „Dann aktualisiert sie einfach“ ist in solchen Systemen keine Architekturentscheidung, sondern eine Verweigerung der Risikobetrachtung.
Gerade dort kann eine starke Isolation sinnvoll sein:
Phase 1├── neuer Host└── vollständige Altanwendung im iframe
Phase 2├── erste neue Capability└── verkleinerte Altanwendung im iframe
Phase 3├── weitere neue Capabilities└── verbleibender Legacy-Bereich im iframe
Ziel└── iframe entfälltIm Migrationsszenario kapselt das iframe einen Bestand, der noch nicht sicher verändert werden kann. Im Dauerbetrieb kapselt es eine fehlende gemeinsame Versionsstrategie.
Das ist ein wesentlicher Unterschied. Die zusätzliche Integrationsarbeit wird im Migrationsfall bewusst in Kauf genommen, um das Risiko der Ablösung zu begrenzen. Jede herausgelöste Capability verkleinert den isolierten Bestand. Die Architektur bewegt sich auf ein definiertes Ziel zu.
In großen Transformationsprojekten endet die Suche nach einer zuverlässigen Trennung stark auseinanderliegender Framework-Generationen nicht selten beim iframe. Das ist nicht zwingend mangelnde technische Kreativität. Häufig zeigt es, dass erst ein eigenes Dokument die benötigte Isolation verlässlich herstellt.
Diese Praxisbeobachtung ist kein allgemeingültiger Beweis und macht das iframe nicht zur Standardlösung. Sie nimmt lediglich ernst, dass große Systeme mit langjähriger Historie manchmal keine engere und zugleich ausreichend sichere Integrationsmöglichkeit besitzen.
Das iframe ist dann nicht das Zielbild. Es ist die kontrollierte Grenze um einen Bestand, der noch nicht sicher migriert werden kann.
Migration braucht ein Zielbild
Abschnitt betitelt „Migration braucht ein Zielbild“Mehrere Major-Versionen können eine sinnvolle Übergangsphase darstellen:
Ausgangslage└── alle Bereiche auf alter Version
Übergang├── erste Bereiche auf Zielversion└── verbleibende Bereiche auf alter Version
Ziel└── alle aktiven Bereiche im vereinbarten VersionskorridorDer Unterschied zwischen Übergang und Dauerzustand liegt nicht in der Technik. In beiden Fällen können mehrere Runtimes parallel existieren. Der Unterschied liegt in Verantwortung, Begrenzung und Richtung.
Eine kontrollierte Ausnahme benötigt mindestens eine definierte Zielversion, einen verantwortlichen Owner, eine Migrationsreihenfolge und einen Rückbauplan. Unterstützte Versionskombinationen müssen dokumentiert werden. Performance-Budgets und Integrationskosten sollten beobachtbar sein. Vor allem braucht die Ausnahme eine zeitliche Begrenzung und eine regelmäßige Überprüfung.
Microfrontends können den Umfang einer Migration verkleinern. Ein Team muss dann nicht zwangsläufig die gesamte Anwendung in einem Release aktualisieren. Sie ersetzen jedoch keine Migrationsstrategie.
Eine Migrationsfähigkeit ist noch keine Empfehlung für einen dauerhaften Versionsmix.
Wenn der Übergang zum Dauerzustand wird
Abschnitt betitelt „Wenn der Übergang zum Dauerzustand wird“Versionsdrift entsteht selten durch eine einzelne große Entscheidung. Sie wächst aus vielen nachvollziehbaren Ausnahmen:
Jahr 1├── Angular 17├── Angular 19└── Angular 22
Jahr 2├── Angular 17├── Angular 21└── Angular 23Ein Bereich migriert, ein anderer bleibt stehen, ein neuer startet auf der aktuellen Zielversion. Jede lokale Entscheidung kann begründbar sein. In Summe entfernt sich die älteste Anwendung dennoch weiter vom Rest der Plattform.
Migrationen werden dadurch nicht kleiner, sondern größer. Gemeinsame Libraries müssen mehrere Generationen berücksichtigen oder ebenfalls aufgespalten werden. Toolchains, Browserunterstützung und Wartungszyklen laufen auseinander. Wissen über alte Versionen muss dauerhaft erhalten bleiben. Die Testmatrix wächst, während Ausnahmen zur Normalität werden.
Besonders problematisch wird es, wenn niemand mehr die Gesamtverantwortung für die technische Plattform besitzt. Dann behandelt jedes Team seine Version als lokale Angelegenheit, obwohl die Nutzer alle Versionen in derselben Anwendung ausführen.
Versionstoleranz ist ein Werkzeug für Übergänge, kein Freibrief für dauerhafte technische Fragmentierung.
Aus einer verschobenen Migration wird sonst verteilte technische Verschuldung.
Die Framework-Version ist ein Plattformvertrag
Abschnitt betitelt „Die Framework-Version ist ein Plattformvertrag“Innerhalb einer gemeinsam komponierten Oberfläche sollte eine zentrale Framework-Major-Version oder ein eng begrenzter Versionskorridor der Normalzustand sein. Mehrere Major-Versionen bleiben eine dokumentierte Ausnahme.
Ein gemeinsamer Workspace kann diese Governance unterstützen. Werkzeuge wie Nx machen zentrale Dependency-Versionen, Projektbeziehungen, betroffene Anwendungen und gemeinsame Migrationsläufe sichtbar. CI-Regeln können unbemerkte Versionsdrift verhindern und dokumentierte Ausnahmen kontrollieren.
Nx löst das Problem nicht automatisch. Nicht das Monorepo erzeugt die gemeinsame Version. Die Organisation muss sie als technischen Plattformvertrag durchsetzen. Das Werkzeug macht diesen Vertrag lediglich sichtbarer und automatisierbarer.
Dasselbe Prinzip lässt sich in Polyrepos umsetzen. Zentrale Policies, automatisierte Update-Prozesse, CI-Prüfungen und eine definierte Kompatibilitätsmatrix können dort dieselbe Governance herstellen. Entscheidend ist nicht die Repository-Grenze, sondern die gemeinsame Verantwortung für die Laufzeitplattform.
Eine Single-Version-Policy bedeutet nicht, dass alle Teams am selben Tag jedes fachliche Release koordinieren müssen. Sie bedeutet, dass die Framework-Runtime nicht als beliebig private Entscheidung behandelt wird, solange die Anwendungen im selben Produkt und Browserkontext komponiert werden.
Eine klare Empfehlung
Abschnitt betitelt „Eine klare Empfehlung“Der Normalzustand sollte eine gemeinsame Framework-Major-Version oder ein bewusst unterstützter, enger Versionskorridor sein.
Ein vorübergehender Versionsmix ist als kontrollierte Migration legitim. Er benötigt einen dokumentierten Grund, einen Owner, ein Ziel und ein Ablaufdatum. Neue Remotes sollten auf der Zielversion beginnen. Alte Versionen sollten nicht durch weitere Consumer und neue Abhängigkeiten verfestigt werden. Zusätzliche Runtimes und iframes brauchen von Anfang an einen Rückbauplan.
Zu vermeiden ist ein beliebiger dauerhafter Versionsmix ohne Zielbild. Er verwechselt technische Flexibilität mit architektonischer Freiheit und lokale Bequemlichkeit mit wirtschaftlicher Tragfähigkeit.
Framework-Versionen sind Teil der Plattform. Wer mehrere davon gleichzeitig betreibt, muss nicht nur beweisen, dass sie geladen werden können. Er muss auch die Runtime-Kosten, die gemeinsamen Browserressourcen, die Integrationsgrenzen und die langfristige Wartung verantworten.
Mehrere Major-Versionen sind technisch ausführbar. Eine gemeinsam genutzte Runtime verlangt jedoch einen gemeinsamen Versionsvertrag. Getrennte Runtimes erhöhen den Ressourcen- und Testaufwand und teilen trotzdem weiterhin denselben Browserkontext.
Vollständige Isolation ist über ein iframe möglich. Dann werden allerdings nicht mehr nur fachliche Ausschnitte komponiert, sondern eigenständige Anwendungen ineinander integriert. Als dauerhafte Zielarchitektur ist dieser Preis meist weder wirtschaftlich noch architektonisch sinnvoll.
Als zeitlich begrenzte Migrationsbrücke kann dieselbe Isolation berechtigt sein. Sie schützt einen Bestand, der noch nicht sicher verändert werden kann, und ermöglicht seine schrittweise Ablösung. Dafür braucht sie ein Zielbild, klare Verantwortung und einen geplanten Rückbau.
Microfrontends dürfen eine Migration entkoppeln. Sie sollten nicht als Begründung dienen, sie dauerhaft zu vermeiden.