Was ist neu in der Angular 8-Version?

So kam Winkel 8 heraus, es enthält eine Efeu-Vorschau, Unterstützung für Servicemitarbeiter, differenzielles Laden und ein paar andere Feinarbeiten. Manfred Steyer erklärt die wichtigsten Änderungen in der neuesten Version.

Wie geplant gab es keine Überraschungen: Die Aktualisierung des Frameworks und der CLI kann mithilfe von ng update erfolgen, und neue Funktionen sind eine schöne Ergänzung zum Motto „Evolution statt Revolution“.

In diesem Artikel spricht der Autor über die wichtigsten neuen Funktionen von Angular 8 und Angular CLI 8. Die im Artikel verwendeten Beispiele finden Sie auf GitHub .

Unter dem Schnitt:


  • Schauen Sie sich zuerst Ivy an
  • Web-Worker
  • Differenzbelastung
  • Faule Lademodule
  • Kritische Änderungen in ViewChild und ContentChild
  • Neue Funktionen ngUpgrade


Schauen Sie sich zuerst Ivy an


Die nächste große Neuigkeit, auf die die Angular-Community wartet, ist Ivy, ein neuer Compiler und auch eine neue Rendering-Engine. Ivy kann erheblich kleinere Bundles und inkrementelle Kompilierungen generieren und ist auch die Grundlage für zukünftige Innovationen in Angular.

Da viele der grundlegenden Teile von Angular geändert wurden, hat das Angular-Team besonderes Augenmerk auf die Kompatibilität mit früheren Versionen gelegt: Nach dem Upgrade auf Ivy sollten vorhandene Anwendungen auf die gleiche Weise wie zuvor funktionieren. Bestenfalls erhalten Sie viel kleinere Bündel. Dies ist nicht desinteressiert, da mehr als 600 Anwendungen bei Google offiziell auf Angular basieren - die tatsächliche Anzahl soll viel höher sein.

Mit Angular 8 steht eine vorläufige Version von Ivy zum Testen zur Verfügung. Der Zweck dieser Version ist es, schnelles Feedback zu erhalten. Aus diesem Grund empfiehlt das Angular-Team, Ivy derzeit nicht im Produkt zu verwenden, sondern weiterhin die klassische Ansichts-Engine zu verwenden (Abb. 1).


Dank der unterschiedlichen Belastung (siehe unten) können die Bündelgrößen jetzt optimiert werden.

Laut Brad Green, CTO des Angular-Teams bei Google, wird Ivy auf der ngconf 2019 die Paketgrößen im Kompatibilitätsmodus in Kombination mit der unterschiedlichen Belastung erheblich verbessern. So können Draufgänger bereits die zukünftige Ivy-API testen. Insbesondere dieser Modus bietet ein großes Optimierungspotential. Die API ist weiterhin als privat markiert. Wenn man sich seine Klassen und Funktionen ansieht, kann man sagen: Sie beginnen mit einem speziellen Symbol ɵ.

Wenn Sie Ivy bereits ausprobieren möchten, können Sie mit dem Schalter enable-ivy ein neues Projekt erstellen:
ng new ivy-project --enable-ivy 

Dieser Schlüssel weist die CLI an, den folgenden Eintrag in der Konfiguration tsconfig.app.json zu speichern:
 "angularCompilerOptions": { "enableIvy": true } 

Dieser Eintrag kann auch manuell nach dem Upgrade auf Version 8 hinzugefügt werden, um eine vorhandene Anwendung mit Ivy zu testen.
Um die Anwendung im Debug-Modus auszuführen, wird empfohlen, AOT zu verwenden:
 ng serve --aot 

Außerdem sollten Sie auf die Größe der Anwendung achten, die mit ng build erstellt wurde. Mit Winkel 9 sollte Ivy standardmäßig aktiviert sein. Bis dahin plant das Angular-Team, weiter daran zu arbeiten, die Kompatibilität mit älteren Versionen sicherzustellen.

Web-Worker


JavaScript ist per Definition Single-Threaded. Aus diesem Grund werden zeitaufwändige Aufgaben wie das Abfragen von Daten normalerweise asynchron ausgeführt. Dies hilft natürlich nicht bei komplexen Berechnungen. Sie werden besonders häufig bei umfangreichen JavaScript-Lösungen verwendet, sodass wir Web-Worker in fast allen Webbrowsern unterstützen. Dies sind Skripte, die vom Browser in einem separaten Thread gestartet werden. Die Kommunikation mit dem Stream auf der Registerkarte Browser erfolgt über Nachrichten.
Obwohl Web-Worker nicht mit Angular als solchem ​​verwandt sind, sollten sie beim Erstellen berücksichtigt werden. Ziel ist es, für jeden Webworker ein Paket bereitzustellen. Diese Aufgabe wurde von der neuen CLI abgeschlossen.
Um eine neue Funktion zu demonstrieren, werde ich JavaScript die Implementierung des sogenannten " n Queens" -Problems zeigen . Die Idee ist, eine Königin hintereinander auf einem Schachbrett zu platzieren, ohne sich gegenseitig bedrohen zu können Die gleiche Zeile, Spalte oder Diagonale sollte keine andere Königin sein.

Der Algorithmus zur Berechnung aller möglichen Lösungen auf einem Schachbrett wird als rechenintensiv angesehen. Obwohl die Berechnungen für ein normales Schachbrett mit acht Zeilen und acht Spalten ziemlich schnell sind, haben herkömmliche Computer mit einem 12 x 12-Brett die Grenze erreicht. Die Lösung für ein 27 x 27-Brett ist der aktuelle Rekord. Für diese Aufgabe wurden russische Supercomputer eingesetzt.
Um diese Berechnung in den Hintergrund zu übersetzen, müssen wir zuerst einen Web-Worker mithilfe der CLI erstellen:
 ng generate worker n-queens 

Diese Anweisung erstellt eine Datei nicht nur für den Mitarbeiter, sondern auch für die für den Erstellungsprozess erforderlichen Konfigurationsdateien und die Einträge in vorhandenen Dateien. Wenn derselbe Ordner eine Komponente mit demselben Namen und einer gemeinsamen Dateierweiterung .component.ts enthält, fügt die CLI auch Code für die Interaktion mit dem Web Worker hinzu.
Der Arbeiter selbst besteht aus einem Zuhörer für die Veranstaltung:
 import nQueens from './n-queens'; addEventListener('message', ({ data }) => { const result = nQueens(data.count); postMessage(result, undefined); }); 

Das Ereignis wird ausgeführt, wenn der Hauptthread eine Nachricht an den Worker sendet. Der Parameter enthält Informationen, die vom Hauptstrom gesendet werden. In diesem Fall wird es durch die count-Eigenschaft begrenzt, die die Größe des Schachbretts festlegt. Nach Auswertung der hier weggelassenen Funktion nQueens sendet eventListener das Ergebnis über postMessage an den Hauptthread zurück. Somit löst der Browser ein Nachrichtenereignis aus.
Die Worker-Klasse wird in der using-Komponente verwendet, um mit dem Worker-Skript zu interagieren:
 const count = parseInt(this.count, 10); const worker = new Worker('../logic/n-queens.worker', { type: 'module' // Worker uses EcmaScript modules }); worker.postMessage({count}); worker.addEventListener('message', (event) => { // tslint:disable-next-line: no-console console.debug('worker result', event.data); // Update chessboard this.processResult(event.data); }); 

Die Komponente sendet über postMessage eine Nachricht mit der gewünschten Größe des Schachbretts an den Arbeiter und startet dort die Berechnung. Es empfängt das Ergebnis über das Nachrichtenereignis.
In Zukunft sorgt die CLI für die korrekte Zusammenstellung von Arbeiterskripten. Der TypeScript-Compiler erkennt sie am Ende von .worker.ts, das in tsconfig.worker.json registriert ist, das mit dem Befehl ng generate worker erstellt wurde . Um sicherzustellen, dass die CLI diese Dateien beim Erstellen der Hauptanwendung nicht erneut beeinflusst, platziert ng generate worker dieselbe Dateivorlage im Ausschlussabschnitt von tsconfig.app.json.
Die vollständige Implementierung erfolgt im Projekt mit Beispielen des Autors. Zum Vergleich kann ein Beispiel für die Aufgabe N Königinnen sowohl im Hauptthread als auch im Webworker gelöst werden. Wenn Sie beispielsweise versuchen, ein Problem für ein 12 x 12-Schachbrett zu lösen, werden Sie feststellen, dass die Benutzeroberfläche im ersten Fall hängt, während die Hintergrundberechnung mit dem Web-Worker die Leistung nicht beeinträchtigt.

Differenzbelastung


Bisher war es üblich, Anwendungen in das gute alte ES 5 zu kompilieren, da diese Version von „JavaScript unserer Väter“ fast überall funktioniert. Dies bedeutet, dass sowohl IE11 als auch der Webcrawler von Google diesen Code ausführen können.
Die neue ES 2015 und ihre nachfolgenden Versionen sind jedoch effizienter: Sie ermöglichen es Ihnen, kompaktere Pakete zu erstellen, und der Browser kann sie auch effizienter interpretieren. Da es bisher üblich war, auf ES 5 als kleinsten gemeinsamen Nenner zurückzusetzen, konnten moderne Browser die neue Version der Sprache leider nicht nutzen.
Jetzt ist es vorbei: Ab Version 8 verfügt die CLI über eine Funktion namens Differential Loading. Die Idee ist, zwei Gruppen von Paketen bereitzustellen: eine basiert auf ECMAScript 5 und wurde für ältere Browser entwickelt, die andere basiert auf einer neuen Version von ECMAScript wie ECMAScript 2015 und bietet modernen Browsern die zuvor genannten Vorteile.
Sie müssen nicht viel arbeiten, um das differenzielle Laden zu ermöglichen. Sie müssen lediglich die Ober- und Untergrenze der unterstützten Versionen von ECMAScript festlegen. Die Obergrenze wird in tsconfig.json wie folgt angegeben:
 "target": "es2015" 

Die Untergrenze wird in der Browserlistendatei definiert. Diese Datei enthält Browser, die nach bestimmten Kriterien unterstützt werden, z. B. nach Marktanteilen. Sie können beispielsweise in der Browserlistendatei gespeichert werden, die die CLI beim Erstellen eines neuen Projekts im Stammverzeichnis des Projekts erstellt:
> 0.5%
last 2 versions
Firefox ESR
not dead
IE 9-11

In diesem Fall enthält die Liste der Browser ES 5-Browser mit einem IE 9-11-Eintrag. Daher definiert die CLI den unteren Schwellenwert als diese Version. Wenn die CLI den Befehl ng build empfängt, wird der Erstellungsprozess für beide Versionen ausgeführt:

Der Nachteil dieses Verfahrens ist folgender: Die für die Montage erforderliche Zeit verdoppelt sich.
Browser können nun entscheiden, welche Version von Paketen heruntergeladen werden soll. Zu diesem Zweck erhalten sie Links zu Skripten im Add-On index.html: Wer auf ECMAScript 5-Pakete verweist, erhält ein Nomodul. Daher ignorieren Browser mit ECMAScript-Unterstützung und daher ECMAScript 2015+ dieses Skript nicht. Andererseits werden ECMAScript 2015+ -Pakete von der CLI mit dem Typ = ”Modul” implementiert. Daher ignorieren ältere Browser diese Skripte:
 <script src="main-es2015.js" type="module"></script> <script src="main-es5.js" nomodule></script> 

Im Gegensatz zu ng build verwenden die restlichen CLI-Befehle nur (!) Die Obergrenze der ES-Unterstützung. In unserem Fall ist dies ECMAScript 2015. Dies geschieht auch aus Gründen der Effizienz: Während des Debuggens und Testens möchten Entwickler das Ergebnis normalerweise so schnell wie möglich sehen, ohne auf den zweiten Build zu warten.

Faule Lademodule


Angular Router unterstützt von den ersten Tagen an das verzögerte Laden. Bisher wurde dies mit der magischen Definition eines ladbaren Moduls erreicht:
 { path: 'lazy', loadChildren: () => './lazy/lazy.module#LayzModule' } 

Der Wert vor # beschreibt den Pfad, der zur Modulimplementierungsdatei führt. Der Wert nach bedeutet die darin enthaltene Klasse. Dieser Beschreibungsstil funktioniert in Angular 8, ist jedoch in Bezug auf dynamische ECMAScript-Importe veraltet:
 { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) } 

Die neue Datensatzoption enthält weiterhin den Dateinamen als magischen Wert. Da Importe jedoch von vielen IDEs unterstützt werden, geben ungültige Werte sofort einen Fehler zurück.

Kritische Änderungen in ViewChild und ContentChild


Es gibt kritische Änderungen bei der Verwendung von ViewChild und ContentChild, die in der Vergangenheit leider nicht immer vorhersehbar funktionierten. Wenn sie in früheren Versionen von einer Komponente zum Abfragen von Elementen verwendet wurden, die nicht in der Strukturanweisung enthalten sind, z. B. ngIf oder ngFor, war das Abfrageergebnis bereits in ngOnInit verfügbar. Andernfalls könnten wir nicht früher als ngAfterViewInit (oder ngAfterContentInit für ContentChild) auf sie zugreifen. Für Elemente, die später aufgrund von Datenbindung in das DOM geladen wurden, sollte der Programmcode ngAfterViewChecked oder dementsprechend ngAfterContentChecked haben.
Da dieses Verhalten verwirrend war, sollte die Komponente jetzt angeben, wann eine Auflösung erfolgen soll:
 @ViewChild('info', { static: false }) paragraph: ElementRef; 

Wenn das statische Flag true ist, versucht Angular, die Elemente zu finden, wenn die Komponente initialisiert wird. Dies funktioniert nur, wenn sie nicht in der Strukturrichtlinie enthalten sind. Bei Verwendung von static: false wird die Auflösung nach dem Initialisieren oder Aktualisieren der Ansicht durchgeführt.
ng update versucht automatisch, den richtigen Wert einzugeben. Wenn dies nicht möglich ist, wird ein Kommentar mit TODO hinzugefügt.
Diese Änderung wirkt sich nicht auf Abfragen mit ViewChildren- und ContentChildren-Dekoratoren aus. Sie hatten immer ein dynamisches Verhalten, neu ausgedrückt im Sinne von statisch: falsch.

Neue Funktionen ngUpgrade


Bisher bestand eines der Probleme mit AngularJS 1.X und Angular in Verbindung mit ngUpgrade darin, dass die Router beider Frameworks aufgrund der URL miteinander konkurrierten. Dies führte zu schwer zu erklärenden Nebenwirkungen. Um dies zu vermeiden, wurde die Möglichkeit hinzugefügt, in beiden Versionen einen einzigen URL-Standortdienst zu verwenden.
Zu diesem Zweck erweiterte das Angular-Team die Funktionen der Angular-Ortungsdienste und stellte damit einen Ersatz für $ location in AngularJS bereit.
Aus diesem Grund wurde dem Standortdienst eine neue onUrlChange-Methode hinzugefügt, um URL-Änderungen zu verfolgen:
 export class AppComponent { constructor(loc: Location, pLoc: PlatformLocation) { loc.onUrlChange((url) => console.debug('url change', url)); console.debug('hostname: ', pLoc.hostname); } } 

Der PlatformLocation-Dienst bietet zusätzlichen Zugriff auf bestimmte Teile der URL. Eine detaillierte Beschreibung, wie der darauf basierende $ location-Ersatz zur besseren Integration von Frameworks verwendet wird, finden Sie hier . Außerdem finden Sie jetzt die AngularJS Lazy Loading-Lösung, die auf dem oben genannten dynamischen ECMAScript-Import basiert.

Fazit


Auch hier hat das Angular-Team sein Wort gehalten: Der Übergang zur neuen Version von Angular ist einfach und beinhaltet keine wesentlichen Änderungen. Im Gegenteil, einige Ecken wurden geglättet, wodurch die Arbeit mit dem SPA-Framework von Google noch komfortabler wurde. Das differenzielle Laden bietet Möglichkeiten zur weiteren Optimierung der Paketgrößen, wenn ältere Browser entweder nicht oder von separaten Paketen unterstützt werden. Die Unterstützung für Web Worker zeigt, dass rechenintensive Aufgaben im Browser verarbeitet werden. Enthusiasten können jetzt ihre ersten Schritte mit Ivy machen.

PS: Dies ist meine erste Übersetzung. Bitte beachten Sie Kommentare, Vorschläge und Fehler in den Kommentaren.

Source: https://habr.com/ru/post/de455493/


All Articles