Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 9 Min.

Ahead-of-Time Compilation

Angular-2-Apps ohne Compiler, dafür mit vorkompilierten Templates ausliefern.
Mit jeder Angular-2-Anwendung­ wird ein Compiler mitgeliefert.­ Dieser sorgt dafür, dass für jedes HTML-Template der Anwendung Code-behind erzeugt wird. Der generierte Code stellt die Verbindung zwischen beiden Welten her und instanziert die verwendeten Angular-Konstrukte. Hierbei spricht man von Just-in-Time-Kompilierung (JIT).Der mit der Anwendung ausge­lieferte JIT-Compiler ist allerdings nicht gerade klein, was größere Dateien und längere Ladezeiten zur Folge hat.Angular 2 bietet mit der Ahead-of-Time (AOT)-Kompilierung einen alternativen Ansatz. Dazu wird der Code-behind für die Templates vorkompiliert und zusammen mit dem übrigen Code ausgeliefert. In diesem Beitrag lesen Sie,  wie das klappt, was Sie dabei beachten müssen und welche Auswirkungen der Prozess der AOT-Kompilierung auf die Performance Ihrer Angular-App hat.Beim Starten einer Webanwendung werden die erforderlichen Ressourcen vom Browser des Benutzers geladen. Dies geschieht auch bei einer Angular-Applikation. Aufgrund der Architektur von Angular wird dabei der Compiler mitgeliefert, damit dieser die Code-behind-Dateien zu den HTML-Templates generieren kann. Der Compiler ist essenziell und realisiert das Binding zwischen dem Code und den Templates­ zum Zeitpunkt des Ladens der Anwendung.Das klingt umständlich und langsam. Könnte man den Overhead vermeiden, profitierte der Benutzer sicher von kürzeren Lade- und Startzeiten. Das haben auch die Entwickler von Angular erkannt und bieten deshalb die Ahead-of-Time-Kompilierung an.Zunächst soll betrachtet werden, was „Ahead of Time“  eigent­lich bedeutet und wie es sich von „Just in Time“ unterscheidet. Anschließend erfahren Sie, wie Sie ein Angular-Projekt mit wenigen Handgriffen für AOT anpassen. Abschließend geht es um die Vor- und Nachteile von AOT, die es zu berücksichtigen gilt.

AOT versus JIT

Bei Ahead-of-Time-Kompilierung wird Code vor dem Ausführen einer Anwendung in Maschinensprache übersetzt. Angewandt auf eine Angular-Anwendung bedeutet dies, dass keine zusätzlichen HTML-Templates an den Browser übertragen werden müssen. Wie bereits erwähnt, entfällt auch der Angular-Compiler beim Payload der Webanwendung. Beides führt dazu, dass die Ladezeiten geringer sind als beim herkömmlichen Vorgehen.
Anhand von Bild 1 wird klar, dass die Konvertierung der ­HTML-Templates und Komponenten zu JavaScript-Dateien nicht mehr zur Laufzeit im Browser ausgeführt wird, sondern bereits beim Bauen der Anwendung. Lediglich der erzeugte Code wird geladen und ausgeführt.Bei der Betrachtung von JIT (siehe Bild 1) zeigt sich, dass das Kompilieren der Ressourcen komplett im Browser des Client-Rechners stattfindet. Hierfür ist das Ausliefern des Compilers notwendig, da das Bootstrapping der Anwendung sonst nicht möglich wäre.Die Verwendung von JIT hat somit zur Folge, dass das Rendern der Anwendung länger dauert. Je größer eine Anwendung wird, desto länger dauert einerseits der Transfer der Daten zum Client und andererseits das Kompilieren, da mehr Ressourcen verarbeitet werden müssen.Im Vergleich dazu wird bei der Ahead-of-Time-Kompilierung bereits ein großer Teil der Tätigkeiten beim Bauen der Anwendung durchgeführt, was die Zeit beim Laden der Oberfläche signifikant reduziert und zu einem besseren Benutzererlebnis führt.

AOT verwenden

Das Schöne an AOT ist, dass es sich sehr einfach umsetzen lässt. Es erfordert keinen großen Zusatzaufwand, da Angular im Hintergrund bereits alles erledigt. Zuallererst muss der Angular-Compiler als Paket eingebunden werden:

npm install <span class="hljs-meta">@angular</span><span class="hljs-regexp">/compiler-cli </span>
<span class="hljs-regexp">  @angular/</span>platform-server 
  <span class="hljs-meta">@angular</span><span class="hljs-regexp">/compiler --save </span>
<span class="hljs-regexp">  node_modules/</span>.bin/ngc -p 
  tsconfig-aot.json 
Der Compiler enthält ein Command Line Interface (CLI), welches Sie mithilfe des Kommandos ngc aufrufen können. Das CLI ist ein Wrapper um den TypeScript-Compiler, deshalb wird eine TypeScript-Konfigurationsdatei als Parameter angegeben, über den sich der Angular-Compiler die relevanten Dateien sucht und den Code generiert.Offiziell ist das CLI nur für Demos, Prototypen oder als ­direkter Ersatz eines Aufrufs des TypeScript-Compilers ­gedacht [1].Wer bereits einen Build-Prozess aufgesetzt hat, zum Beispiel über gulp oder webpack, kann direkt auf das API des Angular-Compilers zugreifen und so die Generierung anstoßen. Für webpack gibt es zum Beispiel ngtools-webpack als npm-Paket, welches als Loader eingebunden werden kann und die AOT-Kompilierung direkt beim Build anstößt.Wer kein TypeScript für seine Angular-Anwendung einsetzt, der kann trotz allem profitieren. Da TypeScript ein ­Superset von JavaScript ist, funktioniert es auch mit Java­Script-Code. Darüber hinaus kann mit TypeScript 2.3 die checkJs-Konfiguration aktiviert werden, wodurch der Type­Script-Compiler auch JavaScript-Dateien auf bestimmte Verstöße prüft.Bei der AOT-Kompilierung werden alle Komponenten als TypeScript-Code generiert. Dadurch bekommt man eine Typprüfung zwischen Template und Komponente. Legen Sie in Ihrem HTML-Template ein Binding für eine Komponente an und es schleicht sich dabei ein Tippfehler ein, dann werden Sie künftig vom TypeScript-Compiler freundlich darauf hingewiesen.Wer sich fragt, welche TypeScript-Version der Angular-Compiler nutzt, wird auf ein Problem stoßen. Hinter den Kulissen verwendet der Angular-Compiler nämlich Tsickle [2], einen TypeScript-to-Closure-Translator, und Closure ist wiederum ein JavaScript-to-better-JavaScript-Compiler [3]. Warum so umständlich? Closure ist ein JavaScript-Compiler aus dem Hause Google, welcher zum Optimieren von JavaScript eingesetzt wird. Beim Übersetzen von TypeScript zu Closure werden alle Typinformationen mitgenommen. Somit hat man die Typisierung von TypeScript kombiniert mit den Optimierungen von Closure. Nachteil dabei ist, dass man darauf angewiesen ist, welche TypeScript-Version Tsickle unterstützt. Eine Alternative gibt es hier aktuell nicht.Sind die Komponenten einmal kompiliert, erhält man verschiedene ngFactories als TypeScript-Dateien. Wer neugierig ist, kann sich diese Dateien einmal genauer anschauen. Der Code, der hier generiert wird, entspricht dem, was der Angular-Compiler im Just-in-Time-Verfahren im Browser erzeugt. Dieser Code wird später mit dem kompletten Script-Bundle mitgeliefert.
Listing 1: Angular-AOT-Bootstrapping
&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; { platformBrowser } &lt;span class="hljs-keyword"&gt;from&lt;/span&gt; &lt;br/&gt;  &lt;span class="hljs-string"&gt;'@angular/platform-browser'&lt;/span&gt;; &lt;br/&gt;&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; { AppModuleNgFactory } &lt;span class="hljs-keyword"&gt;from&lt;/span&gt; &lt;br/&gt;  &lt;span class="hljs-string"&gt;'./app.module.ngfactory'&lt;/span&gt;; &lt;br/&gt;&lt;br/&gt;platformBrowser().bootstrapModuleFactory(&lt;br/&gt;  AppModuleNgFactory);  
Im letzten Schritt ist noch das Angular-Bootstrapping anzupassen. Dabei wird bei der JIT-Kompilierung das Platform-Browser-Dynamic-Modul von Angular in Kombination mit dem eigenen App-Modul verwendet. Bei der AOT-Kompilierung verwendet man das Platform-Browser-Modul und bindet die generierte app.module.ngfactory ein, wie Sie in Listing 1 sehen.Das war’s schon. Nach diesen Anpassungen verwendet Angular die Ahead-of-Time-kompilierten Komponenten, statt diese beim Aufruf zu kompilieren.Da die AOT-Kompilierung durchaus etwas länger dauern kann, sollte man im Build-Prozess zwischen Dev-Umgebung und Produktivumgebung unterscheiden. Es bietet sich an, in der Dev-Umgebung keine AOT-Kompilierung zu verwenden und auf die JIT-Kompilierung zu setzen. Das spart Zeit, da beim Entwickeln häufig neu kompiliert werden muss.In der Produktivumgebung hingegen bietet es sich an, die AOT-Kompilierung zu verwenden, um von den Optimierungen zu profitieren. Ein Nachteil bei diesem Vorgehen ist, dass man dann nicht auf potenzielle Probleme im Binding hingewiesen wird.Wer die Internationalisierung von Angular verwendet, muss bei AOT etwas aufpassen. Bei der JIT-Kompilierung kann im Browser anhand der Sprache des Benutzers ad hoc entschieden werden, welche Übersetzungen verwendet werden sollen. Da bei AOT die Templates bereits vorkompiliert sind, muss für jede Sprache ein eigenes Script-Bundle erzeugt werden.Für diesen Anwendungsfall kann man dem Angular-Compiler als Option die geforderte Sprache und die Übersetzungsdatei mitgeben. Beim Build muss dann für alle verfügbaren Sprachen ein eigenes Script-Bundle erzeugt werden, welches dann im Browser abhängig von der Sprache des Benutzers geladen wird.Wer das Angular CLI zum Erstellen seiner App verwendet, der hat es noch einfacher. Beim Build über das CLI müssen nur die Parameter --prod und --aot angegeben werden, damit die AOT-Kompilierung angestoßen wird. Trotz allem muss auch hier das app Module angepasst werden (siehe Listing 1).

Vor- und Nachteile von AOT

Sie haben bereits gesehen, wie sich Ahead-of-Time- Kompilierung von Just-in-Time unterscheidet, in Bezug darauf, welche Prozessschritte beim Build der Anwendung bereits auf der Server-Seite und welche auf der Client-Seite durchgeführt werden müssen. Zudem wurde gezeigt, mit welchen Handgriffen im Angular-Projekt die Just-in-Time-Kompilierung auf Ahead-of-Time umgestellt werden kann und was bei der Verwendung des Angular-CLI zu beachten ist.Schneller und kleiner – das liest sich zunächst wie ein Werbeslogan, kann aber mit ein paar Selbstversuchen belegt werden. Unter Verwendung von AOT lädt der Browser die bereits vorkompilierte Anwendung, was dazu führt, dass der Code auf der Client-Seite direkt und ohne weitere JIT-Kompilierung ausgeführt werden kann. Außerdem ist in den übertragenen Daten der Angular-Compiler nicht mehr enthalten. Dank der vorkompilierten Templates führt AOT zu einem schnelleren Start der Anwendung im Browser. Auch weil weniger Daten zu übertragen und weniger Ajax-Aufrufe zum Nachladen von Markup- und Style-Dateien erforderlich sind, da diese beim Kompilieren in den JavaScript-Dateien gespeichert wurden.Besonders vorteilhaft ist dies, wenn die Angular-Anwendung auf mobilen Endgeräten ausgeführt werden soll, deren Rechenleistung und Datenübertragungstempo beziehungsweise -kapazität begrenzt sind.Ein wichtiger weiterer Vorteil von Angular-AOT ist, dass der Compiler bereits zur Bauzeit essenzielle Fehlermeldungen liefert, welche den Entwickler davor bewahren, fehlerhaften Code zu publizieren und sich eventuelle Fehlermeldungen vom Kunden zuschicken lassen zu müssen.Wer möchte, kann seine Angular-App noch weiter optimieren, das Stichwort dazu lautet Tree Shaking. Darunter versteht man das Entfernen ungenutzter Abhängigkeiten im Code. Das kann sowohl eigener Code als auch unnötig eingebundener Code aus Bibliotheken sein.Tree Shaking klappt nicht nur in Kombination mit AOT, grundsätzlich lässt sich damit auch JIT-Code entschlacken. Dennoch kann Tree Shaking effizienter auf durch AOT erzeugten Code angewandt werden, da es auch die Templates optimiert. Weitere Informationen dazu liefert die Angular-AOT-Dokumentation [4].Wie zu erwarten war, gibt es auch Nachteile: Einige gängige oder häufig verwendete Code-Patterns, wie Modulexport unter Verwendung von Default- oder String-Interpolation innerhalb von Templates, können nicht mit AOT kompiliert werden. Diese gilt es also zu vermeiden oder durch kompatible Varianten zu ersetzen. Eine gute Übersicht über mögliche Fallstricke bietet das GitHub-Repository von Rangle IO [5].Ein weiterer Nachteil ist, dass die bei der Kompilierung erzeugten Dateien deutlich ausführlicher und für Menschen schlechter lesbar sind als die Artefakte, welche beim JIT-Verfahren an den Client versendet werden. Diesen Kompromiss geht man ein, wenn man sich zugunsten einer optimierten Ladezeit für AOT entscheidet.

Fazit

AOT reduziert die Größe der auszuliefernden Daten und zudem die für das Rendern im Browser benötigte Zeit. Allerdings wird der Benutzer nicht bewusst wahrnehmen, dass ­eine Anwendung besonders performant ist. Das erwartet er von seiner Anwendung einfach. Wäre sie zu langsam, würde er schimpfen. Dem Entwickler aber gibt AOT eine kostengünstige und einfach umsetzbare Möglichkeit zur Optimierung an die Hand, was der Benutzer implizit durch die Verwendung der Anwendung honoriert.AOT bringt daher einen Nutzen, wenn es um das Erstellen der Artefakte geht, welche für ein Release benötigt werden. Für die Entwicklung selbst bestehen zwar Vorteile wie die Fehlermeldungen beim Kompilieren, dennoch kann es für Entwickler performanter sein, wenn lokal eine JIT-Kompilierung im Browser verwendet wird. Änderungen werden damit schneller dargestellt.Durch die Vorteile für den Benutzer, die beherrschbare Konfiguration und die vielen Optimierungsmöglichkeiten geht der Gedanke ganz klar in die Richtung, das Endprodukt unter Verwendung der Angular-Ahead-of-Time-Kompilierung zu erstellen.Auch wenn heute noch viele Konstrukte aus dem Entwickleralltag in Verbindung mit der AOT-Kompilierung nicht direkt unterstützt werden, so ist die Community hinter Angular und der AOT-Kompilierung so groß, dass diese in naher Zukunft benutzbar werden. Wagt man zugleich einen Blick in die Zukunft der Angular-AOT-Kompilierung, so sind die Ambitionen des Teams so hoch gesteckt [6], dass es sich durchaus lohnt, bereits heute vorbereitet zu sein.

Fussnoten

  1. GitHub, Angular Compiler CLI, http://www.dotnetpro.de/SL1711AngularAOT1
  2. GitHub, Tsickle, https://github.com/angular/tsickle
  3. GitHub, Closure Compiler, http://www.dotnetpro.de/SL1711AngularAOT2
  4. Google, Angular-AOT, Tree Shaking, http://www.dotnetpro.de/SL1711AngularAOT3
  5. Rangle IO, Rangle Angular 2 AoT SandBox, http://www.dotnetpro.de/SL1711AngularAOT4
  6. Tobias Bosch, YouTube, The Angular 2 Compiler, http://www.dotnetpro.de/SL1711AngularAOT5

Neueste Beiträge

DWX hakt nach: Wie stellt man Daten besonders lesbar dar?
Dass das Design von Websites maßgeblich für die Lesbarkeit der Inhalte verantwortlich ist, ist klar. Das gleiche gilt aber auch für die Aufbereitung von Daten für Berichte. Worauf besonders zu achten ist, erklären Dr. Ina Humpert und Dr. Julia Norget.
3 Minuten
27. Jun 2025
DWX hakt nach: Wie gestaltet man intuitive User Experiences?
DWX hakt nach: Wie gestaltet man intuitive User Experiences? Intuitive Bedienbarkeit klingt gut – doch wie gelingt sie in der Praxis? UX-Expertin Vicky Pirker verrät auf der Developer Week, worauf es wirklich ankommt. Hier gibt sie vorab einen Einblick in ihre Session.
4 Minuten
27. Jun 2025
„Sieh die KI als Juniorentwickler“
CTO Christian Weyer fühlt sich jung wie schon lange nicht mehr. Woran das liegt und warum er keine Angst um seinen Job hat, erzählt er im dotnetpro-Interview.
15 Minuten
27. Jun 2025
Miscellaneous

Das könnte Dich auch interessieren

UIs für Linux - Bedienoberflächen entwickeln mithilfe von C#, .NET und Avalonia
Es gibt viele UI-Frameworks für .NET, doch nur sehr wenige davon unterstützen Linux. Avalonia schafft als etabliertes Open-Source-Projekt Abhilfe.
16 Minuten
16. Jun 2025
Mythos Motivation - Teamentwicklung
Entwickler bringen Arbeitsfreude und Engagement meist schon von Haus aus mit. Diesen inneren Antrieb zu erhalten sollte für Führungskräfte im Fokus stehen.
13 Minuten
19. Jan 2017
Evolutionäres Prototyping von Business-Apps - Low Code/No Code und KI mit Power Apps
Microsoft baut Power Apps zunehmend mit Features aus, um die Low-Code-/No-Code-Welt mit der KI und der professionellen Programmierung zu verbinden.
19 Minuten
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige