paint-brush
Den Monolithen brechen: Ein umfassender Leitfaden zu Code-Splitting-Technikenvon@aleksandrguzenko
8,117 Lesungen
8,117 Lesungen

Den Monolithen brechen: Ein umfassender Leitfaden zu Code-Splitting-Techniken

von Aleksandr Guzenko11m2023/04/24
Read on Terminal Reader
Read this story w/o Javascript

Zu lang; Lesen

Mit Micro-Frontends (MFs) können Entwicklungsteams für große Projekte organisiert werden. Bei MFs handelt es sich eher um eine **organisatorische Entscheidung** darüber, wie die Entwicklungskomplexität in einem großen Projekt verwaltet werden soll. MFs werden Ihnen nicht dabei helfen, das Frontend zu beschleunigen, einige Implementierungen werden es im Gegenteil sogar verlangsamen.
featured image - Den Monolithen brechen: Ein umfassender Leitfaden zu Code-Splitting-Techniken
Aleksandr Guzenko HackerNoon profile picture


In den letzten Jahren wurde in der Front-End-Community der Begriff „Micro-Frontend“ (im Folgenden als MF bezeichnet) aktiv diskutiert und verwendet. Verschiedene Unternehmen teilen ihre Ansätze zur Organisation einer solchen Architekturlösung , aber bisher gibt es kaum eine Beschreibung der Probleme, die MFs im Web lösen sollen, der Kriterien für ihre Anwendbarkeit und der Einschränkungen bei der Verwendung.


In diesem Artikel habe ich versucht, verschiedene Arten der Organisation von MFs zu vergleichen und Empfehlungen dazu zu formulieren, wo welcher Ansatz verwendet werden sollte.


Der Artikel kann sowohl für Analysten und Entwicklungsteams beim Entwerfen der Architektur eines Projekts und beim Entwerfen von Prozessen als auch für Produktbesitzer nützlich sein, da die Einführung von MFs eine überschaubarere Entwicklung ermöglichen kann.

Microfront-Ansatz: Was ist das und warum wird es benötigt?

Bevor wir zur Definition von MF übergehen, werfen wir einen Blick auf einige Probleme, die in Projekten auftreten können:


  1. Sie haben ein großes Projekt . Die Größe eines Projekts ist in der Regel subjektiv und kann empirisch anhand des Funktionsumfangs und der Anzahl der Entwickler ermittelt werden. Wenn Sie genug Arbeit haben, um 1-2 Front-Ender zu puzzeln, und diese gleichzeitig nicht „ihre Ellbogen drücken“, ist dies ein kleines Projekt, 3-6 ist mittelgroß und mehr als 6-8 ist bereits ein großes Projekt .


  2. Sie haben ein großes Team . Auch hier sind es empirisch gesehen mehr als 10 Front-Ender, der Rest der Teilnehmer zählt nicht. In der Regel kann ein Team dieser Größe bereits in Teilteams aufgeteilt werden, die bestimmte Funktionen zur Unterstützung übernehmen und über eigene Analysten, Backender und QA verfügen.


  3. Du hast eine tolle Funktionalität. Ein einzelner Entwickler kann nur einen Codeabschnitt für sein Unterteam pflegen. Die Verfeinerung des restlichen Codes kann aufgrund der Unkenntnis des Themenbereichs oder der Komplexität der Implementierung der Logik von Drittanbietern kostspielig sein.


Probleme können sich noch verschärfen:

  • der Wunsch, den Stapel zu wechseln;

  • eine Unternehmensanforderung, eine Familie verwandter Projekte zu unterstützen.


Wie kann man Beziehungen zwischen so vielen Menschen organisieren? Wie können Sie Prozesse bei einem Projekt dieser Größenordnung aufbauen? Wie können Sie Verantwortungsbereiche richtig abgrenzen? Je mehr Probleme Sie gesammelt haben, desto eher lohnt es sich, über die Einführung eines mikrofrontalen Ansatzes nachzudenken. Denn dies ist eine natürliche Fortsetzung des evolutionären Trends in der Entwicklung hin zur Zerlegung des Codes und des Projektteams.





Somit ist der MF-Ansatz die Aufteilung einer monolithischen Front in separate Codebasen, die in separaten Repositorys gespeichert sind und auf die separate Unterteams Zugriff haben. Gleichzeitig können/sollten sie über eigene Demostände, Tests und Release-Zyklen verfügen. Dementsprechend ist die Mikrofront ein abnehmbarer Teil der Schnittstelle. Eine Aufteilung nach Seiten ist nicht erforderlich, die Funktionalität kann durchgängig sein (z. B. Corporate UI-Kit).


Unabhängig davon ist hervorzuheben, dass MFs eher eine organisatorische Entscheidung darüber sind, wie die Entwicklungskomplexität in einem großen Projekt verwaltet werden soll. MFs werden Ihnen nicht dabei helfen, das Frontend zu beschleunigen, einige Implementierungen werden es im Gegenteil sogar verlangsamen. Dieser Ansatz beschleunigt jedoch die Entwicklung selbst aufgrund der Zuweisung von Verantwortungsbereichen und isolierten Tests.





Microfrontends vs. Lazy Loading

Im Gegensatz dazu ist Lazy Loading im Vergleich zu MFs erwähnenswert. Sie lösen unterschiedliche Probleme, aber manchmal denken die Leute, dass es nur um eine Sache geht, weil wir in beiden Fällen die Anwendung „aufteilen“.


Lazy Loading löst das Leistungsproblem: wie man den Benutzer nicht dazu zwingt, das gesamte Front-End-Bundle zu laden, wie man nicht länger als nötig wartet und wie man die Front auf dem Client schneller startet und früher mit der Interaktion beginnt.


MFs lösen das Leistungsproblem nicht, sondern verschärfen es manchmal sogar. Sie tragen jedoch dazu bei, die Entwicklung für ein bestimmtes Unterteam komfortabler zu organisieren und die oben genannten Probleme zu minimieren.

Buildtime vs. Runtime

Lassen Sie uns nun über den Ansatz sprechen, MFs in einer einzigen Anwendung zu kombinieren. Wofür Sie sich auch entscheiden, es sollte für den Benutzer wie eine einzelne Anwendung aussehen. Sie können sowohl in der Assembly-Phase als auch dynamisch zusammenführen – während der Codeausführung auf Benutzerseite.


Daher können alle Arten der Organisation von MFs der Build-Zeit oder der Laufzeit zugeordnet werden. Jedes hat seine Vor- und Nachteile.


Bauzeit

Laufzeit

Typprüfung

+

-

Versionierung

+

keinen Sinn

Unabhängige Bereitstellung

-

+


Die Typprüfung spielt in der modernen Entwicklung eine wichtige Rolle. Wenn es von separaten unabhängigen Unterteams geleitet wird, wird es zu einer Notwendigkeit. So stellen Sie die Konsistenz von MFs sicher, dass sie Daten korrekt verwenden und im richtigen Format weitergeben usw.


Durch das Zusammenführen von Mikrofronten zum Zeitpunkt der Erstellung wird Ihnen nicht die Möglichkeit genommen, Typen zu überprüfen. Im Falle einer Runtime-Union müssen Sie Integrationstests schreiben, damit die Front in der Produktion nicht plötzlich „explodiert“.


Versionierung und unabhängige Bereitstellung sind sehr widersprüchlich:


  • Versionierung bedeutet, dass Sie jede Version des MF des anderen Teams übernehmen können. Dies gilt insbesondere dann, wenn Sie zusätzliche Arbeiten durchführen müssen, um die Abhängigkeiten des MF-a von anderen zu aktualisieren. Jedes Team wählt einen besseren Zeitpunkt für das Upgrade.


  • Der unabhängige Einsatz verleiht den Teams mehr Autonomie und Unabhängigkeit. Es ist wichtig, immer die neuesten Versionen von MFs zu verwenden. Dies erfordert Abwärtskompatibilität.


Die Versionierung lässt sich auch mit der Laufzeitzusammenführung umsetzen, dies ist jedoch nicht praktikabel. Es ist sinnvoll, die Runtime nur zum Zweck der unabhängigen Bereitstellung zu kontaktieren, und letztere kann nicht zusammen mit der Versionierung existieren.


Als nächstes sehen wir Beispiele für spezifische Implementierungen jedes Ansatzes zur Kombination von MFs.

Ansätze zur Organisation von Mikrofrontends

Iframe

Die älteste Art, MFs zu organisieren. iframe ist ein spezielles Tag zum Übergeben der Adresse einer Ressource, die auf der Hauptseite angezeigt wird. Das Ergebnis ist eine Site innerhalb einer Site.




Zu den Vorteilen zählen die einfache Implementierung, die vollständige Isolierung von Logik und Stilen, die Möglichkeit einer unabhängigen Bereitstellung und das Fehlen einer Bindung an Frameworks.


Diese Vorteile gehen mit Leistungseinbußen einher, da jedes Einfügen eines Iframes zu einer Belastung der Ressourcen führt. Das lässt sich nicht vermeiden: Versuche, einen DOM-Knoten zu debuggen und erneut anzuhängen, werden die zuvor geladenen Ressourcen nicht speichern, Sie müssen sie erneut herunterladen. Sie können Leistungseinbußen minimieren, indem Sie Caching konfigurieren.


Dazu müssen Sie die zeitbasierte Cache-Invalidierung für unveränderliche Ressourcen konfigurieren. Glücklicherweise hängen alle modernen CLI-Dateien standardmäßig einen kleinen Hash an den Namen der gesammelten JS- und CSS-Dateien an. Zu den Nachteilen dieser Methode gehört, dass Suchroboter nicht in der Lage sind, Iframes für die anschließende Indizierung zu rendern.


Vorteile

Nachteile

Einfache Implementierung

Leistung

Isolation von Logik und Stilen

SEO

Unabhängige Bereitstellung


Framework-unabhängig



WebComponents

Die Front-End- Community hat lange auf die Entwicklung nativer Komponenten gewartet, aber am Ende erlangten sie nie die von vielen erwartete Massenpopularität. Die drei beliebtesten Frontend-Frameworks (React, Vue, Angular) erstellen Komponenten immer noch auf ihre eigene Art und Weise.


Trotz der Möglichkeit, MFs auf Webkomponenten zu erstellen, habe ich dies in der Praxis noch nicht gesehen. Und das ist kein Zufall, es gibt eine Reihe von Blockern:


  • Entweder ist libs Lit oder Stencil nicht populär genug und nicht verbreitet genug. Darüber hinaus gibt es auf dem Markt nicht genügend Spezialisten, die damit umgehen können oder bereit sind, zu lernen.


  • Eckige Elemente oder Vue-Custom-Element bleiben Exoten. In einer nativen Umgebung macht ihre Verwendung wenig Sinn. Wenn Sie die Anwendung bereits aufgeteilt haben, dann in gewöhnliche NPM-Pakete, damit Sie die Komponenten später nach Belieben verbinden können. Die Verwendung von Webkomponenten mit anderen Frameworks ist unvernünftig, da Sie neben den generierten Komponenten auch eine Miniversion des Frameworks verbinden müssen, auf dem sie geschrieben wurden.


  • Es kann kostspielig sein, komplexe Funktionalitäten in Webkomponenten zu verschieben. Da Sie die Kommunikation Ihrer Komponente mit dem Rest der Anwendung konfigurieren müssen, ist es möglicherweise nicht gerechtfertigt, eine ganze Seite in einer separaten benutzerdefinierten Komponente herauszunehmen.


  • Suchroboter können keine Webkomponente erstellen, was Auswirkungen auf die SEO-Optimierung hat.

Vorteile

Nachteile

Geeignet für übergreifende Funktionalität

Schwierig umzusetzen

Kompatibel mit jedem Framework

SEO

Isolation von Logik und Stilen



NPM

Die Entwicklung mit npm-Paketen hat viele Vorteile. Entwickler importieren einfach die benötigten Komponenten und Dateien aus der Bibliothek. Gleichzeitig bleibt die Typisierung im Projekt erhalten, es erfolgt eine Versionierung. Der Build ist optimal: Tree-Shaking funktioniert (Entfernen nicht verwendeter Code während des Builds) und Entwickler können Lazy Loading problemlos einrichten.



Allerdings hat diese Methode auch ihre Nachteile. In diesem Fall sind Sie gezwungen, die Einheit des Stapels sowie Versionen Ihrer MFs und deren transitive Abhängigkeiten beizubehalten. Andererseits kann dies ein Pluspunkt sein: Durch die Veröffentlichung einer neuen Version des Pakets können andere Teams die Aufgabe übernehmen, die Version ihrer Abhängigkeiten zu einem für sie passenden Zeitpunkt zu erhöhen, wenn sie zusätzliche Funktionen einführen müssen oder umgekehrt , etwas entfernen.


Vorteile

Nachteile

Leistung

Verfügt nicht über eine unabhängige Bereitstellung

SEO

Einzelstapel

Typprüfung


Versionierung



Git-Submodule (oder eine andere Möglichkeit, Monorepos wie Lerna zu erstellen)

Als Alternative zu MF für npm-Pakete sollten Sie Git-Submodule in Betracht ziehen. Tatsächlich handelt es sich hierbei um Repositories innerhalb eines Repositorys, innerhalb dessen es auch Repositories geben kann. Sie können in Submodulen unterschiedliche Zweige festlegen. Feature-Module können beispielsweise einen Dummy-Zweig haben, in dem sich nichts befindet. Dies ist notwendig, damit der Zusammenbau schneller geht und andere Module keine Nebenwirkungen verursachen. Dummy-Branches können für lokale Entwicklung und Tests sehr praktisch sein.







In seinen Vor- und Nachteilen kommt dieser Ansatz den NPM-Paketen sehr nahe. Wir importieren auch einfach etwas, aber aus einem benachbarten Ordner und nicht aus einem Paket, und verwenden es.


Werfen wir einen Blick auf die Unterschiede zwischen den beiden Methoden:


  • NPM-Pakete sind tatsächlich ein endliches, mäßig isoliertes Mikroprodukt mit eigenen Releases und Versionierungen. Alles ist darauf ausgerichtet, wiederverwendbare Funktionalität zu schaffen. Die Anwendung kann jedoch komplex/umständlich und stinkend sein, sodass es recht kostspielig sein kann, einen großen Monolithen zu verpacken. Hier wäre es sinnvoll, Submodule in Betracht zu ziehen, da Sie damit das Repository sehr grob aufteilen können, wenn wir den Ordner ohne zusätzliche Vorbereitung in ein separates Repository verschieben.


  • NPM-Pakete können rekursiv verschachtelt werden. Auch Submodule, aber auf Assembly-Ebene können sie beginnen, die Funktionalität zu duplizieren, wenn eines der Submodule mehrmals in verschiedenen Ordnern als separates Submodul enthalten ist. In diesem Fall lohnt sich der Einsatz eines flacheren Modulaufbaus.


  • Wenn Sie eine Funktion schnell in allen Paketen auf einmal einführen müssen, kann die paketübergreifende Entwicklung äußerst umständlich sein. Während bei Submodulen alles beim Alten bleibt, können Sie Änderungen vornehmen, die sich auf andere Submodule auswirken. In diesem Fall ist das Debuggen einfach. Aber am Ende werden Sie die Änderungen selbst nicht zusammenführen – auf der Ebene der Zusammenführungsanforderung kann es sein, dass ein Drittanbieterteam, dessen Modul Sie berührt haben, von Ihnen verlangt, den Code mit seinen Regeln in Einklang zu bringen.


npm

Git-Submodule

Wiederverwendbarkeit

Grobe Kürzung der Funktionalität

Beliebig verschachtelte Abhängigkeiten

Flache Struktur

Plattformübergreifende Entwicklung

Entwicklung mit beliebigen Modulen zählt


Single-Spa

Single-Spa ist im Wesentlichen ein Framework, das andere Frameworks kombiniert. Unglaublich leistungsstarke Technologie, die eine Vielzahl von Nuancen verbirgt, ist ein Thema für einen separaten Artikel.

Das Schema ähnelt iframe, aber das Laden des MF erfolgt jetzt über nativen Import + Importmap oder über Systemjs, wenn Polyfills benötigt werden.





Im Gegensatz zu allen Methoden zur Organisation von MFs ist diese in hohem Maße darauf zugeschnitten, verschiedene Frameworks untereinander zu kombinieren. Es ist jedoch davor zu warnen, Technologie um der Technologie willen zu nutzen. Wenn es möglich ist, mit einem Stapel auszukommen, müssen Sie ihn verwenden. Die Entwicklung kann für immer mit der Wartung eines technisch komplexen Projekts und der Behebung von Fehlern aufgrund der Nebenwirkungen verschiedener Anwendungen belastet sein. Der Benutzer kann sich unwohl fühlen, weil. Die Menge an Code zum Herunterladen auf den Client wird erhöht (die Kerne verschiedener Frameworks für verschiedene Funktionalitätsteile + der Kern des Single-Spa selbst und seiner Plugins).

Vorteile

Nachteile

Unabhängige Bereitstellung

Umfangreiche Dokumentation, die noch nicht alle Fälle abdeckt

Framework-unabhängig

Schwierigkeiten mit SEO

Leistungsstarke CLI



Webpack 5 Modul Federation

Ein Webpack 5-Plugin, das speziell für die Erstellung von MFs entwickelt wurde. Vielversprechende Technologie: ein kleines Build-Plugin für korrektere Bündelung und dynamische Importe zur Laufzeit.


Das Schema wiederholt Single-Spa fast eins zu eins, aber jetzt werden dynamische Importe zum Laden von MFs verwendet



Vorteile

Nachteile

Unabhängige Bereitstellung

niedriges Niveau

Einfache Umsetzung


Kompatibel mit SSR




Wie wählen Sie aus, was Sie in Ihrem Fall verwenden möchten?

Werfen wir einen Blick darauf, was angewendet werden kann und wofür:


  • iframe – eine einzelne Einfügung für eine Kombination von Unstimmigkeiten

  • Webkomponenten – wenn Sie eine kleine End-to-End-Funktionalität benötigen, ohne an ein Framework gebunden zu sein, wie z. B. ein Unternehmens-UI-Kit

  • npm-Pakete – wenn eine Wiederverwendbarkeit zwischen Projekten besteht und/oder Sie eine Typprüfung während der Build-Zeit benötigen

  • Git-Submodule – wenn Sie ein Projekt grob zerlegen und Verantwortungsbereiche verteilen müssen

  • Single-Spa – wenn ein starker Bedarf besteht, mehrere Frameworks auf unbestimmte Zeit zu kombinieren, vorzugsweise ohne SSR

  • Modulföderation – alle anderen Szenarien für die Verwendung von MFs, vorbehaltlich der Einheit des Stapels.


Jeder Ansatz ist auf seine Weise gut und alles sollte seinen Platz haben. Bevor Sie auf MFs umsteigen, empfehlen wir Ihnen, darüber nachzudenken, ob Sie diese wirklich benötigen. Welcher Ansatz auch immer gewählt wird, es wird unweigerlich etwas auf der Ebene der Entwicklung, CI/CD oder Leistung komplizieren. Wenn es Möglichkeiten gibt, auf einem einzelnen Stapel und einer monolithischen Anwendung zu bleiben, nehmen Sie diese Gelegenheit gerne an.


Und vergessen Sie natürlich nicht die Benutzer . Letztendlich laden sie alle verbundenen Frameworks herunter und ertragen mögliche Fehler durch die falsche Integration von MFs in verschiedene Funktionalitätsteile. Die Unternehmen wiederum müssen für die Umsetzung und Betreuung all dessen aufkommen.