Jun 23, 2020
Im Arbeitsleben fast aller Entwickler gibt es Momente, in denen ein Upgrade in Betracht gezogen wird. Entweder durch den Entwickler selbst oder durch den Kunden, den Anbieter usw. Upgrades können auf verschiedene Arten von Softwareaspekten angewendet werden. Einer dieser Aspekte kann das Framework sein, das für die Erstellung einer Anwendung verwendet wird und das nicht unbedingt am einfachsten zu handhaben ist.
Dann stellt sich die Frage: "Warum sollte man überhaupt ein Upgrade in Betracht ziehen?"
In diesem Artikel werden wir anhand des Angular-Frameworks als Versuchskaninchen Beispiele anführen und unsere Erfahrungen teilen, um Ihnen bei der Beantwortung dieser Frage zu helfen.

Wenn Sie ein Frontend-Framework aktualisieren, brauchen Sie in der Regel einen guten Plan, der oft Folgendes umfasst:
Welches Framework veröffentlicht zweimal im Jahr neue Versionen? Angular gehört zu den Frameworks, die manche Frontend-Entwickler als nicht erstrebenswert ansehen, da es zu einer ständigen Unterbrechung des gesamten Entwicklungsprozesses führen könnte, indem viel Zeit nur für Upgrades eingeplant wird. Selbst wenn die Unterschiede zwischen benachbarten Versionen gering sind, müssen bei einem großen Projekt dennoch genügend Zeitfenster für Upgrades eingeplant werden.
Stellen wir uns ein Angular-Projekt mit 3 gemeinsamen Modulen und 15 untergeordneten Modulen (einige davon eng gekoppelt) vor, mit Hunderten von Komponenten, die von 4 verschiedenen Teams gepflegt werden (die sich nicht unbedingt nach Modulen unterscheiden). Hinzu kommt, dass die Anwendung eine beträchtliche Anzahl externer Pakete für verschiedene Zwecke verwendet, bei denen es zu Abhängigkeitsproblemen kommen kann, und die Vorbereitung eines Zeitfensters nur für ein Upgrade hat erhebliche Auswirkungen auf die Planung, Sprints, Roadmaps usw. der Teams. Natürlich kann niemand ohne eine ausführliche und korrekte Analyse bestimmen, wie lange der Upgrade-Zeitraum dauern kann.
Und es geht nicht nur um die Planung (einige Teams können an Themen mit höherer Priorität arbeiten) und den Entwicklungsaufwand (einige Aspekte des Upgrades könnten mehr als ein einfaches Refactoring erfordern), die Änderungen als Ergebnis des Upgrades müssen später verifiziert werden, was in der Regel das Testen des gesamten Produkts bedeutet.
In der Einleitung haben wir eine allgemeinere Frage gestellt: "Warum sollte man überhaupt ein Upgrade in Betracht ziehen? "
Beginnen wir mit drei verschiedenen Beispielen für dieselbe Anwendung: eine, die die neueste Version des Frameworks verwendet, und zwei weitere, die eine bzw. drei Versionen dahinter liegen. Das bestmögliche Ergebnis, das für ein Upgrade spricht, ist, dass die neueste Version stabil ist und mehr Vorteile genutzt werden können. Das bedeutet, dass sich die Zeit, die in das Upgrade investiert wurde, einmal mehr als bei der zweiten Anwendung und dreimal mehr als bei der dritten Anwendung, gelohnt hat.
Somit befindet sich die dritte Anwendung in einem Zustand, in dem sie entweder ein riskantes direktes Upgrade durchführen oder drei aufeinander folgende Upgrades ohne viel Zeit dazwischen einplanen muss, um die erste Anwendung einzuholen und die Vorteile der neuesten Version zu nutzen.
Im schlimmsten Fall sind die Vorteile der neuesten Version (wenn es denn welche gibt) weder für die aktuelle Entwicklung noch für die Wartung geeignet, und das Team, das an der ersten Anwendung arbeitet, hat durch die Planung und Durchführung des Upgrades Zeit verloren, um nichts weiter zu erreichen als eine Zahl zu erhöhen. Ganz zu schweigen davon, dass auch die Stabilität der neuesten Version in Frage gestellt werden kann.
Glauben Sie, dass Sie bereits eine Antwort haben? Nun, so offensichtlich ist sie nicht, also lassen Sie uns tiefer graben.
Im Vergleich zu anderen Frameworks gibt Angular auch an, dass die neuen Änderungen, die mit jeder neuen Version einhergehen, Ihre aktuelle Anwendung tatsächlich optimieren und die kommende Entwicklung erleichtern können. Wir werden jedoch keine Details zu diesen Verbesserungen nennen, da dies den Rahmen dieses Themas sprengen würde.
Die meisten Angular-Experten und -Mitwirkenden raten zu folgendem Upgrade-Muster: Aktualisieren Sie stets auf die neueste stabile Version. Das bedeutet, dass Sie jedes Mal, wenn eine neue Hauptversion veröffentlicht wird, auf diese Version aktualisieren sollten, bevor die nächste Hauptversion erscheint. Wenn also Ihre aktuelle Version mehrere "Nummern" hinterherhinkt und Sie beschließen, auf die neueste stabile Version zu aktualisieren, wird empfohlen, dies schrittweise zu tun, d. h. mehrere Upgrades durchzuführen, um die Spitzenversion zu "erreichen".

Die Quintessenz ist, dass Sie durch ein Upgrade auf nur eine höhere Version:
Unser Projekt begann mit Version 2. Seitdem haben wir ein einziges großes Upgrade durchgeführt, direkt auf Version 5. Danach konnten wir aufgrund von engen Zeitplänen, Roadmaps und anderen Prioritäten nicht genügend Zeit und Ressourcen für ein Upgrade aufbringen. Als wir uns schließlich für ein Upgrade entschieden, war die letzte offizielle stabile Version 8.
Während der Planungsgespräche gab es die Option, direkt auf v8 umzusteigen, aber eine große Menge an Code, der das alte @angular/http-Paket verwendet, hat uns davon überzeugt, dass wir bis zum Abschluss des Refactorings zumindest auf v6 migrieren und alle neuen Optionen nutzen können, die das nächste Upgrade erleichtern könnten. Daher sieht der Weg zum Erreichen unseres Ziels vor der Veröffentlichung von v9 wie folgt aus: v5 -> v6 -> v7 -> v8. Das bedeutet, dass insgesamt drei verschiedene nachfolgende Upgrades durchgeführt werden müssen, was vermutlich kürzer ist als ein direktes Upgrade.
Da wir bereits das HttpClient-Paket erwähnt haben, blieb es für mehrere größere Angular-Versionen veraltet. Es ist jedoch immer wichtig, zumindest die Deprecations in Ihrem Projekt im Auge zu behalten, wenn Sie sich nicht rechtzeitig darum kümmern können. Sie sollten nicht darauf warten, dass die veralteten Funktionen aus einer zukünftigen Version, auf die Sie aktualisieren möchten, vollständig entfernt werden!
Warum lohnt es sich, die wichtigsten Details dieses speziellen Upgrades von v5 auf v6 zu erläutern?
Abgesehen von den Problemen, mit denen Sie sich möglicherweise auseinandersetzen müssen und die Sie stundenlang untersuchen, führt v6 einige bahnbrechende Änderungen ein, wie z.B.:
Es fehlt eine genaue Dokumentation für das Upgrade, insbesondere auf v6. Das liegt vor allem daran, dass diese Versionen zu der Zeit die neuesten waren und die Befehle zum Upgrade von Angular/CLI gleich geblieben sind. Wenn also jemand nach einer Anleitung für ein Upgrade auf eine bestimmte Version sucht, die nicht die neueste ist, führt dies zu einem Upgrade auf die letzte offizielle Version statt auf die gewünschte Version.
Wir begannen mit der offiziellen Empfehlung von Angular und mussten bald feststellen, dass dies bei weitem nicht ausreichte. Obwohl der Upgrade-Leitfaden drei verschiedene Optionen für die Anwendungskomplexität anbietet, gibt es wahrscheinlich keine ausreichenden Untersuchungen über einen signifikanten Pool großer und komplizierter Projekte und wie sich der Upgrade-Prozess unter diesen Bedingungen verhält.
Der erste Schritt war ein großer Fehler - anstatt auf die Basisversion 6.0.0 zu aktualisieren, versuchten wir, direkt auf die v6-lts zu migrieren, d. h. auf die neueste Nebenversion 6.2.9. Auf diese Weise entstehen viel mehr Probleme mit Paketabhängigkeiten als erwartet, die in den meisten Fällen einzeln gelöst werden müssen.
Wir mussten das Upgrade von vorne beginnen. Daher raten wir, auf die erste Hauptversion zu aktualisieren, d. h. nicht direkt auf eine der kleineren Angular-Versionen zu aktualisieren, es sei denn, Sie versuchen, die Hauptversion zu wechseln.
Zum Beispiel:
Nachdem wir schließlich das Upgrade einer Umgebung erfolgreich durchgeführt hatten, entdeckten wir, dass bei der Durchführung des Upgrades in anderen Umgebungen weitere Probleme auftreten können. Wir haben alle diese Probleme mit ihren Lösungen gesammelt und dann eine Prozedur erstellt, die für das Projekt an anderer Stelle gilt.
Da Angular in den meisten Fällen node.js verwendet, um die Vorteile des Paketmanagers npm zu nutzen, ist als erstes zu prüfen, welche Version Sie derzeit verwenden - in unserem Fall 7.6.0. Die offizielle Empfehlung von node.js für Angular v6 ist, mindestens 8.0.0 als Mindestanforderung zu verwenden. Zum Zeitpunkt des Upgrades war die letzte stabile Node-Version 12.7.0, und wir entschieden uns, diese zu verwenden. Überraschenderweise erwies sich dieser Ansatz als Fehlschlag, und zwar aus den folgenden zwei Gründen:

Erstens erfordern einige Pakete einen bestimmten Bereich von Node-Versionen. Ein solches Paket ist das Paket sass bindings provider node-sass. Wenn dieses Problem nicht gelöst wird, kann es zu CSS-Inkonsistenzen kommen, z. B. wird das Grid-Layoutmodul nicht erkannt oder die LibSass-Bibliothek nicht referenziert.
Zweitens: Da es verschiedene Möglichkeiten gibt, node.js zu installieren und zu aktualisieren, kann es passieren, dass Sie mehrere Versionen gleichzeitig in Ihrem System haben. Und auch wenn Sie jeweils nur eine verwenden können, sind die anderen Node-Versionen immer noch in einem aktiven Zustand und stören gelegentlich die Einrichtung und den Betrieb der Anwendung. In manchen Umgebungen kann sogar eine parallele Version laufen, ohne dass Sie dies bemerken.
Um diese beiden Probleme zu vermeiden, empfehlen wir die Verwendung von nvm für die Verwaltung von Node auf Ihrem lokalen Rechner und insbesondere die Verwendung der Option "Deaktivieren", damit Sie sicher sein können, dass es keine anderen Versionen von Node gibt als die, die Sie tatsächlich für Angular verwenden möchten.
Aber zuerst müssen Sie die richtige Version finden. Leider gibt es keine einfache Möglichkeit, dies automatisch zu tun, außer eine Version nach der anderen zu prüfen, beginnend mit der minimal erforderlichen Version, die offiziell angekündigt ist. In unserem Fall haben wir mit 8.0.0 begonnen und mit 8.9.0 aufgehört, wobei wir die meisten Versionen ausprobiert haben. Auch wenn zum Zeitpunkt des Upgrades offizielle 10.x-Versionen von node.js verfügbar waren und für die Verwendung empfohlen wurden, raten wir, unabhängig vom Zweck, die minimal erforderliche Version zu verwenden, um andere Kompatibilitätsprobleme zu vermeiden.
Fast das Gleiche passiert mit der TypeScript-Version. Die offizielle Empfehlung für die Mindestanforderung lautet 2.7, aber tatsächlich war die niedrigste Version, die keine Probleme verursachte, 2.7.2. Und auch hier hing es mit Problemen der Paketabhängigkeit zusammen.
Eine merkwürdige Sache, die Sie beachten müssen, ist, dass, obwohl Ihre noImplicitAny-Option in Ihrer tsconfig.json auf false gesetzt ist, Sie immer noch Kompilierfehler bei nicht deklarierten Variablen bekommen können. Sie können das Projekt trotzdem kompilieren und ausführen, aber wenn Sie diese Fehler wirklich loswerden wollen, müssen Sie die Deklaration dieser Variablen auf any setzen.
DasJQuery-Paket kann oft Teil Ihres Projekts sein, insbesondere wenn Sie Bootstrap-Steuerelemente einbinden, was zu einem weiteren Grund für Abhängigkeitsprobleme führt. Aber keine Angst, in diesem Fall können Sie zumindest diese Probleme leicht nachvollziehen, da sie fast ausschließlich mit den Bootstrap-Paketen verbunden sind.
Hier würden wir nur empfehlen, die niedrigstmögliche Version des jQuery-Pakets zu verwenden, es sei denn, die abhängigen Pakete verbieten dies. Die neueste jQuery-Version zum Zeitpunkt des Upgrades war 3.4.1, aber wir blieben bei 2.2.0 in unserer package.json.
Version 6 des RxJS-Pakets bringt Änderungen mit sich, die Sie zu einer Menge Code-Refactoring zwingen, das hauptsächlich durch unterschiedliche Import-Anweisungen, Methoden, Operatoren und so weiter verursacht wird. Daher ist es sehr wahrscheinlich, dass während der Kompilierungszeit Fehler auftreten, die mit den Referenzänderungen von observable, promise, zip und anderen "reactives" zusammenhängen:
ERROR in node_modules/rxjs/internal/types.d.ts(81,44): error TS1005: ';' expected.
Was, wenn wir Ihnen sagen, dass Sie die Abwärtskompatibilität wiederherstellen können, indem Sie nur ein weiteres Paket installieren? Sie werden mir sicher zustimmen, dass dieser Vorschlag besser ist, als Hunderte von Codezeilen zu ändern. Version 6 des rxjs-compat-Pakets muss zusammen mit RxJS v6 installiert werden, und Sie werden jede Zeile Code beibehalten. Dies ist ein wirklich gutes Beispiel dafür, dass die Aufnahme neuer Kompatibilitätspakete in das Projekt nicht viel Code-Refactoring mit sich bringt (in unserem Fall hat es dies sogar verhindert) und keine zusätzliche Komplexität mit sich bringt.
Zu diesem Zeitpunkt kompiliert Ihre Angular 6-Anwendung ohne Probleme und Sie können sie ausführen, um zu überprüfen, dass nichts kaputt ist. Sie öffnen die ersten Seiten und etwas scheint anders zu sein als vorher. Einige Html-Elemente sind aneinander geklebt, als gäbe es keinen Abstand mehr zwischen ihnen. Der erste Gedanke, der Ihnen in den Sinn kommt, ist, dass wahrscheinlich wieder ein css-bezogenes Paketproblem aufgetreten ist.
"angularCompilerOptions": { "preserveWhitespaces" : true }
Glücklicherweise steht dies im Zusammenhang mit der Änderung der standardmäßigen Angular-Compiler-Option zur Erhaltung der Leerzeichen. Setzen Sie einfach die Eigenschaft preserveWhitespaces in den angularCompilerOptions der Datei tsconfig.json auf true und die Seiten werden wieder wie zuvor gerendert.
Die Umgebung, in der das Upgrade zum ersten Mal durchgeführt wird, erfordert mehr Untersuchungen und eine größere Anzahl von Befehlen, die ausgeführt werden müssen. Eine bestimmte Liste von Befehlen muss auf dem bestehenden Projekt ausgeführt werden, und als Ergebnis des Upgrades wird es einige Änderungen geben, hauptsächlich an den Konfigurationsdateien wie angular.json und package.json. Hier ist die Reihenfolge, die im Allgemeinen funktionieren sollte, vorausgesetzt, Sie haben node.js richtig eingerichtet:
npm uninstall -g @angular/cli rm -rf node_modules npm cache clean //bei Bedarf verwenden Sie -force //an diesem Punkt können Sie package-lock.json aus Ihrem Projekt entfernen, falls vorhanden npm install -g @angular/cli@6.0.0 npm install @angular/cli@6.0.0 //an diesem Punkt sollte die Version Ihrer Angular-bezogenen Pakete auf 6 geändert werden.0.0 ändern und die Carets entfernen, falls vorhanden npm install npm install rxjs@6.0.0 rxjs-compat@6.0.0 -save //optional, nur ausführen, wenn Sie rxjs-Probleme haben, wie im vorherigen Abschnitt beschrieben
Wenn Sie aus irgendeinem Grund Schwachstellen entdecken, empfehlen wir, diese nacheinander zu beheben, indem Sie die erforderlichen Pakete sorgfältig installieren oder die Versionen der vorhandenen Pakete erhöhen. Sie können den npm audit-Befehl verwenden, um die vorgeschlagenen Eingriffe zu melden und die Probleme manuell zu lösen (ja, das wird wahrscheinlich einige Zeit in Anspruch nehmen, aber Sie können die Probleme leicht lokalisieren), aber bitte verwenden Sie auf keinen Fall sofort npm audit fix, da es versuchen könnte, die Schwachstellen auf einmal zu beheben.
Wenn das Verfahren erfolgreich ist, sollte es auf andere ähnliche oder andere Umgebungen angewandt werden und dürfte neben der Installation der Pakete aus einer bereits geänderten package.json-Datei weniger manuelle Eingriffe erfordern. Die folgende Befehlsfolge sollte ausreichend sein:
npm uninstall -g @angular/cli rm -rf node_modules npm cache clean //bei Bedarf -force verwenden //an dieser Stelle können Sie package-lock.json aus Ihrem Projekt entfernen, falls vorhanden npm install -g @angular/cli@6.0.0 //package.json hat bereits die erforderlichen Änderungen npm install
Vermeiden wir es, die neuen Möglichkeiten zu beschreiben, die v6 nach dem Upgrade mit sich bringt, und erwähnen wir stattdessen nur einige Konsequenzen, die Sie beachten müssen, hauptsächlich wegen der Änderung des Formats der angular.json-Datei. Um die Anwendung unter verschiedenen, nicht standardmäßigen Umgebungen zu bedienen, muss nun das Konfigurationsargument anstelle der vorherigen env gesetzt werden, ebenso wie das Zielargument, das unnötig ist und über die Umgebung angegeben wird. Der Übergang sieht wie folgt aus:
ng serve -env={Ihre_env} -> ng serve -configuration={Ihre_env}
oder
ng serve -env={Ihre_env} -> ng serve -c {Ihre_env}
Was wurde in der package.json nach dem Upgrade außer den Angular-bezogenen Paketen geändert oder hinzugefügt? Wenn Sie die Sicherheitslücken richtig angehen, müssen Sie nicht viel ändern, nicht einmal das vorgeschlagene zone.js-Paket. Hier ist unsere Liste der Änderungen:
Hinzufügen von "@angular/platform-server": "6.0.0" "rxjs-compat": "6.0.0" "@angular-devkit/build-angular": "~0.6.0" Geändert "@angular/animations": "6.0.0", "@angular/common": "6.0.0", "@angular/compiler": "6.0.0", "@angular/core": "6.0.0", "@angular/forms": "6.0.0", "@angular/http": "6.0.0", "@angular/platform-browser": "6.0.0", "@angular/platform-browser-dynamic": "6.0.0", "@angular/router": "6.0.0", "@angular/cli": "6.0.0", "@angular/compiler-cli": "6.0.0", "typescript": "2.7.2"
Ein weiterer Vorteil ist, dass sich das Upgrade weder auf die Pakete protractor und karma auswirkt, noch deren Konfigurationen ändert, was bedeutet, dass Sie keine Maßnahmen in Bezug auf Ihre Unit-Tests oder e2e-Tests ergreifen müssen.
Nachdem Sie unsere Erfahrungen sorgfältig gelesen haben, können Sie leicht zu dem Schluss kommen, dass das Upgrade von Angular auf eine beliebige Version im Allgemeinen ein projektspezifisches Problem ist, das eine sorgfältige Planung und die ernsthafte Berücksichtigung einiger Schlüsselpunkte erfordert, die in den vorherigen Abschnitten erläutert wurden.
Was haben wir aus dieser Erfahrung gelernt? Wir haben gelernt, dass wir versuchen werden, den Upgrade-Prozess jedes Mal zu priorisieren, wenn eine neue Hauptversion auftaucht, und jede Lösung für ein kniffliges Problem zu teilen, auf das wir während des Prozesses stoßen könnten.
Wir sind uns sicher, dass, wenn es da draußen im Universum noch jemanden gibt, der aus irgendeinem Grund immer noch auf diese veraltete Version upgraden möchte, die Strategie, die wir in diesem Artikel beschrieben haben, definitiv nützlich sein wird.
Sie sind Angular-Entwickler und suchen ein Unternehmen, bei dem Sie eine dynamische Karriere in Ihrem Interessengebiet aufbauen können, mit Fachleuten zusammenarbeiten, um Einblicke in die Branche zu gewinnen, und kontinuierliche Lern- und Entwicklungsmöglichkeiten genießen können? Wenn das nach Ihnen klingt, dann sollten Sie sich unsere aktuellen Stellenangebote ansehen.

Velimir Graorkoski
Software Engineer - AI
Vertrauen bei führenden Unternehmen weltweit




Intertec


Aneta Pejchinoska


Intertec