Zu diesem Buch – sowie zu vielen weiteren O’Reilly-Büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei oreilly.plus+: www.oreilly.plus |
3. AUFLAGE
Das Praxisbuch zu Grundlagen und Best Practices
Manfred Steyer
Lektorat: Ariane Hesse
Fachliche Unterstützung: Hans-Peter Grahsl
Korrektorat: Sibylle Feldmann, www.richtiger-text.de
Satz: III-satz, www.drei-satz.de
Herstellung: Stefanie Weidner
Umschlaggestaltung: Michael Oréal, www.oreal.de
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
ISBN:
Print 978-3-96009-166-0
PDF 978-3-96010-576-3
ePub 978-3-96010-577-0
mobi 978-3-96010-578-7
3. Auflage 2021
Copyright © 2021 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
Dieses Buch erscheint in Kooperation mit O’Reilly Media, Inc. unter dem Imprint »O’REILLY«.
O’REILLY ist ein Markenzeichen und eine eingetragene Marke von O’Reilly Media, Inc. und wird mit Einwilligung des Eigentümers verwendet.
Hinweis:
Dieses Buch wurde auf PEFC-zertifiziertem Papier aus nachhaltiger Waldwirtschaft gedruckt. Der Umwelt zuliebe verzichten wir zusätzlich auf die Einschweißfolie.
Schreiben Sie uns:
Falls Sie Anregungen, Wünsche und Kommentare haben, lassen Sie es uns wissen: kommentar@oreilly.de.
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.
5 4 3 2 1 0
Vorwort
1Projekt-Setup
Visual Studio Code
Angular CLI
Node.js und Angular CLI installieren
Ein Projekt mit der CLI generieren
Angular-Anwendung starten
Build mit CLI
Projektstruktur von CLI-Projekten
Internet Explorer 11
Eine Style-Bibliothek installieren
Alternativen zu Bootstrap
Zusammenfassung
2Erste Schritte mit TypeScript
Motivation
Mit TypeScript starten
Hallo Welt!
Variablen deklarieren
Ausgewählte Datentypen in TypeScript
Ein erstes Objekt samt Modul
Auto-Importe mit Visual Studio Code
Klassen
Funktionen und Lambda-Ausdrücke
Interfaces und Vererbung
Interfaces
Klassenvererbung
Type Assertion (Type Casting)
Abstrakte Klassen
Zugriff auf die Basisklasse
Ausgewählte Sprachmerkmale
Getter und Setter
Generics
Exceptions
Spread-Operator
Strikte Null-Prüfungen
Asynchrone Operationen
Callbacks und die Pyramide of Doom
Promises
async und await
Bedeutung von Promises in Angular
Zusammenfassung
3Eine erste Angular-Anwendung
Angular-Komponente erzeugen
Komponentenlogik
Auf das Backend zugreifen
Templates und die Datenbindung
Two-Way-Binding
Property-Bindings
Direktiven
Pipes
Event-Bindings
Das gesamte Template
Komponenten einbinden
Anwendung ausführen und debuggen
Anwendung starten
Fehler in der Entwicklerkonsole entdecken
Die Anwendung im Browser debuggen
Debuggen mit Visual Studio Code
Zusammenfassung
4Komponenten und Datenbindung
Datenbindung in Angular
Rückblick auf AngularJS 1.x
Property-Binding
Event-Bindings
Das Zusammenspiel von Property- und Event-Bindings
Bindings im Template
Two-Way-Bindings
Eigene Komponenten mit Datenbindung
Überblick
Vorbereitungen
Eine Komponente mit Property-Bindings
Komponenten mit Event-Bindings
Komponenten mit Two-Way-Bindings
Life-Cycle-Hooks
Ausgewählte Hooks
Experiment mit Life-Cycle-Hooks
Angular und Zyklen
DateControl mit Life-Cycle-Hooks
Zusammenfassung
5Services und Dependency Injection
Ein erster Service
Services austauschen
Services mit klassischen Providern konfigurieren
Einen Service lokal registrieren
Arten von Providern
useClass
useValue
useFactory
useExisting
multi
Konstanten als Tokens
Zusammenfassung
6Pipes
Überblick
Built-in-Pipes
Eigene Pipes
Pure Pipes
Implementierung einer einfachen Pipe
Pipes registrieren und nutzen
Weiterführende Konstellationen
Pipes und Objekte
Pipes und Direktiven
Pipes und Services
Aufräumarbeiten mit ngOnDestroy
Zusammenfassung
7Module
Motivation
Eine Angular-typische Modulstruktur
Shared Modules
Feature-Modules
Root-Modules
Module reexportieren
Zusammenfassung
8Routing
Überblick
Erste Schritte mit dem Router
Routing-Konfiguration für das AppModule einrichten
Routing-Konfiguration für Feature-Modules einrichten
Platzhalter in AppComponent hinterlegen
Hyperlinks zum Aktivieren von Routen einrichten
Parametrisierte Routen
Arten von Routing-Parametern
Parameter in Komponenten auslesen
Parametrisierte Routen konfigurieren
Auf parametrisierte Routen verweisen
Hierarchisches Routing mit Child-Routes
Überblick über Child-Routes
Child-Komponente implementieren
Child-Komponente registrieren
Hyperlinks zum Aktivieren von Child-Routen einrichten
Aux-Routes
Platzhalter für Aux-Routes
Komponente für Aux-Route erzeugen
Konfiguration für Aux-Route
Verweise auf Aux-Routes einrichten
Mit dem Query-String und dem Hash-Fragment arbeiten
QueryString und Hash-Fragment programmatisch beeinflussen
Query-String und Hash-Fragment deklarativ beeinflussen
Query-String und Hash-Fragment auslesen
HTML5-Routing vs. Hash-Routing
PathLocationStrategy
HashLocationStrategy
Zusammenfassung
9Template-getriebene Formulare und Validierung
FormsModule einbinden
Eingaben validieren
Zugriff auf den Zustand des Formulars
Bedingte Formatierung von Eingabefeldern
Eigene Validierungsdirektiven
Eine erste Validierungsdirektive erstellen
Parametrisierbare Validierungsdirektiven
Multi-Field-Validatoren erstellen
Asynchrone Validatoren
Komponente zum Präsentieren von Validierungsfehlern
Die Standardsteuerelemente von HTML nutzen
Checkboxen
Radiobuttons
Drop-down-Felder
Zusammenfassung
10Reaktive Formulare
Erste Schritte mit reaktiven Formularen
Modul einbinden
Das Formular mit einem Objektgraphen beschreiben
Reactive Formulare mit dem FormBuilder beschreiben
Einen Objektgraphen an ein Formular binden
Werte ins Formular schreiben
Validatoren
Synchrone Validatoren
Parametrisierte Validatoren
Asynchrone Validatoren
Multi-Field-Validatoren für reaktive Formulare
Geschachtelte Formulare
Geschachtelte FormGroups
Wiederholgruppen mit FormArray
Dynamische Formulare
Zusammenfassung
11Reactive Extensions Library for JavaScript (RxJS)
Grundlegende Typen von RxJS
Observables, Observer und Operatoren
Observables instanziieren
Subjects
Observables vs. Promises
Observables in Promises umwandeln
Promises in Observables umwandeln
Gruppen von Operatoren
Creation Operators
Transformation Operators
Filtering Operators
Join Operators
Error Handling Operators
Multicasting Operators
Utility Operators
Reaktiver Entwurf
Flattening
Datenflüsse kombinieren
Der Operator combineLatest
combineLatest vs. withLatestFrom
Der Operator merge
Multicasting
Motivation für Multicasting
Hot vs. Cold Observables
Fehlerbehandlung
Observables schließen
Reaktive Services
Zusammenfassung
12Testautomatisierung
Jasmine und Karma
Aufbau eines Jasmine-Tests
Tests mit Karma ausführen
Karma auf dem Build-Server
Angular und Jasmine
Komponenten mit dem TestBed testen
Arbeiten mit Attrappen (Mocks)
Gray-Box-Tests mit Spys
HTTP-Zugriffe simulieren
Asynchrone Tests
Templates mit DOM-Zugriffen testen
Direktiven testen
Pipes testen
Testabdeckung ermitteln
Zusammenfassung
13Performancetuning
Optimierte Datenbindung mit OnPush
Datenbindung visualisieren
Immutables
Immutables und Datenbindung
Observables und Datenbindung
Immutables und/oder Observables
Manuelle Änderungsverfolgung
Lazy Loading von Routen
Routen für das Lazy Loading einrichten
Lazy Loading im Browser nachvollziehen
Lazy Loading und Tree-Shakable Provider
Lazy Loading, klassische Provider und Shared Modules
Korrekte Nutzung von SharedModules beim Einsatz von Lazy Loading
Preloading
Preloading aktivieren
Eigene Preloading-Strategien entwickeln
Selektives Preloading mit eigener Preloading-Strategie
Zusammenfassung
14.Querschnittsfunktionen
Guards
Das Aktivieren von Routen verhindern
Das Deaktivieren einer Komponente verhindern
Events
Resolver
Vorbereitungen
Resolver erzeugen und verwenden
HttpInterceptoren
Zusammenfassung
15.Authentifizierung und Autorisierung
Cookie-basierte Security
Cookies und XSRF
Tokenbasierte Security
OAuth 2 und OpenID Connect
OAuth 2
Benutzer mit OpenID Connect authentifizieren
JSON Web Token
OAuth-2- und OIDC-Flows
OAuth 2 und OIDC mit Angular nutzen
Zusammenfassung
16Internationalisierung
I18N mit dem Angular-Compiler
Überblick
@angular/localize installieren
Texte markieren
Strings in der Komponentenklasse markieren
Texte extrahieren
Übersetzte Texte in Builds integrieren
Sprache beim Einsatz von ng serve festlegen
Übersetzungstexte zur Laufzeit angeben
Grammatikalische Formen berücksichtigen
Unterschiedliche Formate unterstützen
Manuell weitere Formate laden
ngx-translate
Überblick
Bibliothek installieren und konfigurieren
Sprachdateien bereitstellen
Texte einbinden
Texte zur Laufzeit laden
Sprachwechsel
Grammatikalische Formen berücksichtigen
Unterschiedliche Formate nutzen
Lazy Loading
Zusammenfassung
17Reaktive Zustandsverwaltung mit NGRX (Redux)
Zustandsverwaltung mit Services
Das Redux-Muster
NGRX einrichten
Building-Blocks implementieren
State modellieren
Actions festlegen
Reducer definieren
Effect einrichten
Auf den Store zugreifen
Debuggen mit dem Store
Selektoren
Ein erster Selektor
Selektoren verschachteln
Meta-Reducer
Zusammenfassung
18Details zu Komponenten und Direktiven
Vorbereitungen
Weiterführende Aspekte von Komponenten
Content Projection
Parent-Komponenten referenzieren
View und Content
Kommunikation über Template-Variablen
Kommunikation über Services
Attributdirektiven
Direktiven definieren
Mit der Umwelt kommunizieren
Direktiven und Template-Variablen
Strukturelle Direktiven
Templates und Container
Microsyntax
Eine einfache DataTable umsetzen
ViewContainerRef direkt zum Einblenden von Templates verwenden
Bestehende ViewContainer ergänzen
Dialoge dynamisch einblenden
ViewContainerRef direkt zum dynamischen Erzeugen von Komponenten verwenden
Komponenten für Formularfelder
Ausgaben formatieren und Eingaben parsen
Eigene Formularsteuerelemente
Zusammenfassung
19Wiederverwendbare Bibliotheken und Monorepos
Monorepo erstellen
Aufbau von Bibliotheken
Bibliothek in Monorepo ausprobieren
npm-Paket bauen und bereitstellen
npm-Paket konsumieren
Zusammenfassung
Index
Vor etwas mehr als zehn Jahren galt für gute Webanwendungen noch die Regel, so viele Aufgaben wie möglich auf dem Server zu erledigen. Inzwischen stützen sich moderne Webanwendungen jedoch auf clientseitige Techniken, allen voran JavaScript. Dies steigert die Benutzerfreundlichkeit und schafft die Möglichkeit, die jeweilige Anwendung an die Auflösungen und Formfaktoren der vielen unterschiedlichen klassischen und mobilen Plattformen anzupassen.
Single Page Applications (SPAs) bilden einen derzeit äußerst beliebten Architekturstil für solche Webanwendungen. Wie ihr Name schon vermuten lässt, bestehen SPAs aus lediglich einer einzigen Seite, die ein Browser auf klassischem Weg abruft und anzeigt. Alle weiteren Seiten und Daten bezieht die SPA bei Bedarf über direkte HTTP-Zugriffe per JavaScript.
Das populäre JavaScript-Framework Angular, das von Google entwickelt wird, hilft Ihnen beim Erstellen von Anwendungen, die diesen Architekturstil verfolgen. Angular bietet unter anderem Unterstützung für die Datenbindung, für das Validieren von Daten sowie das Arbeiten mit Vorlagen. Darüber hinaus stellt Angular Konzepte zur Verfügung, mit denen Sie den Quellcode strukturieren und wartbare, wiederverwendbare sowie testbare Programmteile erschaffen können. Das vorliegende Buch präsentiert die Möglichkeiten von Angular. Dabei beschränkt es sich nicht nur auf die Grundlagen, sondern geht auch auf die zugrunde liegenden Konzepte ein.
Das Buch richtet sich an Entwickler, die bereits grundlegende Erfahrungen mit HTML, CSS und JavaScript gesammelt haben und nun mit Angular SPAs entwickeln wollen. Dabei bezieht es sich auf die Version 12 von Angular, die beim Verfassen der Texte die aktuellste Version war. Aufgrund des evolutionären Charakters von Angular gehen wir jedoch davon aus, dass dieses Buch auch für viele darauffolgende Versionen geeignet ist.
Mit diesem Buch verfolgen wir das Ziel, Ihnen anhand von Beispielen zu zeigen, wie Sie Angular zur Entwicklung von Single Page Applications nutzen können. Dabei gehen wir auf die Möglichkeiten von Angular ein und präsentieren auch Lösungen für Aspekte, die Angular nicht direkt unterstützt.
Über http://www.ANGULARarchitects.io/leser stellen wir Ihnen sämtliche in diesem Buch präsentierten Quellcodebeispiele sowie Web-APIs zur Verfügung, die die Beispiele zu Demonstrationszwecken nutzen und die Sie auch in eigene Projekte einbinden können. Darüber hinaus werde ich auf dieser Seite weitere Informationen zu Angular sowie gegebenenfalls Errata zum vorliegenden Buch veröffentlichen. Daneben bietet die Website Ihnen die Möglichkeit, mit mir als Autor direkt in Kontakt zu kommen.
Kursiv
Wird genutzt für neue Begriffe, URLs, Dateinamen und E-Mail-Adressen
Nichtproportionalschrift
Programmlistings und Codeelemente im Fließtext wie Methoden, Module o.Ä. werden in dieser Schrift dargestellt.
Dieses Symbol steht für Hinweise und allgemeinere Anmerkungen. |
|
Dieses Symbol steht für Tipps. |
Das Buch besteht aus 19 Kapiteln. Die folgende Auflistung zeigt, was diese bieten:
Der Autor bietet Schulungen und Beratung zu Angular an. Informationen dazu finden Sie unter http://www.ANGULARarchitects.io.
Meinen Dank für ihre Mitwirkung an diesem Buch möchte ich aussprechen an
Moderne JavaScript-Projekte gleichen immer mehr klassischen Anwendungen: Sie nutzen Compiler, um moderne typsichere Sprachen wie TypeScript in handelsübliches JavaScript zu übersetzen. Zusätzlich verwenden sie Werkzeuge, mit denen sie optimierte Bundles erzeugen. Damit sind JavaScript-Dateien gemeint, die sich aus mehreren einzelnen Dateien zusammensetzen.
Durch dieses Vorgehen müssen nur noch wenige Dateien auf dem Server platziert sowie in den Browser geladen werden. Ersteres erhöht den Komfort beim Deployment, und Letzteres verbessert die Startgeschwindigkeit der Anwendung. Außerdem kommen in modernen JavaScript-Projekten auch Werkzeuge zur Testautomatisierung zum Einsatz.
Dieses Kapitel zeigt, wie sich ein Projekt-Setup für Angular, das diesen Kriterien genügt, einrichten lässt. Es beginnt mit der Installation und Einrichtung von Visual Studio Code, der in diesem Buch verwendeten Entwicklungsumgebung. Danach wendet sich das Kapitel dem Angular Command Line Interface (CLI) zu. Dabei handelt es sich um eine vom Angular-Team bereitgestellte Konsolenanwendung, die viele Aufgaben rund um die Angular-Entwicklung automatisiert. Schließlich erfahren Sie in diesem Kapitel auch, wie ein mit der CLI generiertes Projekt aufgebaut ist.
Wir nutzen in diesem Buch die freie Entwicklungsumgebung Visual Studio Code (https://code.visualstudio.com). Sie funktioniert auf allen wichtigen Betriebssystemen (Linux, macOS, Windows) und ist äußerst leichtgewichtig. Visual Studio Code unterstützt auch die Sprache TypeScript. Bei dieser handelt es sich um eine typsichere Obermenge von JavaScript, die für die Angular-Entwicklung verwendet wird.
Außerdem existieren zahlreiche Erweiterungen, die die Arbeit mit Frameworks wie Angular vereinfachen. Um Erweiterungen zu installieren, klicken Sie auf das Symbol Extensions in der linken Symbolleiste. Anschließend können Sie nach Erweiterungen suchen und diese installieren (siehe Abbildung 1-1).
Abbildung 1-1: Erweiterungen in Visual Studio Code installieren
Für die Entwicklung von Angular-Lösungen empfehlen wir die folgenden Erweiterungen:
Angular Language Service
Der Angular Language Service wird vom Angular-Team bereitgestellt und erlaubt Angular-bezogene Codevervollständigungen in HTML-Templates. Außerdem weist der Language Service auch auf mögliche Fehler in HTML-Templates hin.
Angular Schematics
Erlaubt das Generieren von Building-Blocks wie Angular-Komponenten über das Kontextmenü von Visual Studio Code.
Debugger for Chrome
Erlaubt das Debuggen von JavaScript-Anwendungen, die in Chrome ausgeführt werden.
Bitte installieren Sie diese Erweiterungen. Wir werden bei Bedarf in den einzelnen Kapiteln darauf zurückkommen.
Neben Visual Studio Code haben wir auch mit den kommerziellen Produkten WebStorm, PhpStorm bzw. IntelliJ von Jetbrains (https://www.jetbrains.com/) sehr gute Erfahrungen gemacht. Es handelt sich bei diesen drei Lösungen eigentlich um das gleiche Produkt in verschiedenen Ausprägungen. PhpStorm unterstützt zum Beispiel darüber hinaus PHP, während IntelliJ zusätzlich viele Annehmlichkeiten für Java-Entwickler mit sich bringt. Diese Lösungen sind zwar etwas schwergewichtiger als Visual Studio Code, bieten dafür jedoch ab Werk zahlreiche Features, wie umfangreiche Refactoring-Möglichkeiten oder Test-Runner für Unit-Tests. |
|
Tatsächlich sind Visual Studio Code und WebStorm/IntelliJ mit Abstand die am häufigsten eingesetzten Entwicklungsumgebungen, auf die wir bei unseren Kundenprojekten im Angular-Umfeld stoßen. |
Um keine Zeit mit dem Einrichten aller benötigten Werkzeuge zu verlieren, bietet das Angular-Team das sogenannte Angular Commandline Interface, kurz Angular CLI (Angular CLI (https://cli.angular.io)), an. Die CLI generiert nicht nur das Grundgerüst der Anwendung, sondern auf Wunsch auch die Grundgerüste weiterer Anwendungsbestandteile wie z.B. Komponenten.
Außerdem kümmert sie sich um das Konfigurieren des TypeScript-Compilers und einer Build-Konfiguration zur Erzeugung optimierter Bundles. Werkzeuge für die Testautomatisierung richtet die CLI ebenfalls ein.
Die CLI lässt sich leicht über den Package-Manager npm beziehen, der sich im Lieferumfang von Node.js (nodejs.org) befindet. Außerdem nutzt sie Node.js als Laufzeitumgebung. Deswegen sollten Sie zur Vorbereitung eine aktuelle Node.js-Version von Node.js (https://nodejs.org) herunterladen und installieren. Die Autoren haben gute Erfahrungen mit den jeweiligen Long-Term-Support-Versionen (LTS-Versionen) gemacht. Der Einsatz älterer Versionen kann zu Problemen führen.
Sobald Node.js installiert ist, kann die CLI mittels npm eingerichtet werden:
npm install -g @angular/cli
Der Schalter -g bewirkt, dass npm das Werkzeug systemweit, also global, einrichtet, sodass es überall zur Verfügung steht. Ohne diesen Schalter würde npm das adressierte Paket lediglich für ein lokales Projekt im aktuellen Ordner einrichten. Nach der Installation steht die CLI über das Kommando ng zur Verfügung.
Ein Aufruf von
ng new flight-app
generiert das Grundgerüst einer neuen Angular-Anwendung, die den Namen flight-app erhält. Dazu stellt es uns ein paar Fragen (siehe Abbildung 1-2):
Abbildung 1-2: ng new stellt ein paar Fragen, bevor es ein neues Projekt generiert.
Je nach Angular-Version können diese Fragestellungen etwas variieren. Wir gehen hier von folgenden Einstellungen aus:
Add Angular Routing
Diese Frage beantworten wir hier mit No. Um das Thema Routing kümmert sich Kapitel 8.
Stylesheet Format
Wir empfehlen hier SCSS, eine Obermenge von CSS. Die Angular CLI kompiliert diese Dateien für den Browser nach CSS.
Da ng new auch zahlreiche Pakete via npm bezieht, kann der Aufruf etwas länger dauern.
Seit Version 12 verwendet die CLI standardmäßig den sogenannten Strict Mode. In diesem Modus führen sowohl der TypeScript-Compiler als auch Angular selbst strengere Code-Prüfungen durch. Hierdurch sollen Programmierfehler rascher entdeckt werden. Falls Sie diese strengeren Prüfungen nicht verwenden wollen, verwenden Sie den Schalter --strict: ng new flight-app --strict false |
|
Wir gehen in in diesem Buch jedoch davon, dass der Strict Mode aktiviert ist. Das entspricht auch den Empfehlungen des Angular-Teams. |
Um Ihre Anwendung zu starten, wechseln Sie in den generierten Projektordner. Dort bauen Sie mit ng serve die Anwendung und stellen sie über einen Demowebserver bereit:
cd flight-app
ng serve -o
Der Schalter -o öffnet einen Browser, der die Anwendung anzeigt. Standardmäßig findet sich diese Anwendung unter http://localhost:4200. Ist Port 4200 schon belegt, erkundigt sich ng serve nach einer Alternative. Außerdem nimmt der Schalter --port den gewünschten Port gleich beim Start von ng serve entgegen:
ng serve -o --port 4242
Die im Browser angezeigte Anwendung sieht wie in Abbildung 1-3 aus. Auch hier kann es von Version zu Version zu Abweichungen kommen.
Abbildung 1-3: Generierte Angular-Anwendung
Der für die Entwicklung gedachte Befehl ng serve macht aber noch ein wenig mehr: Er überwacht sämtliche Quellcodedateien und stößt das Kompilieren sowie Generieren der Bundles erneut an, wenn sie sich ändern. Danach aktualisiert er auch das Browserfenster.
Um das auszuprobieren, können Sie mit Visual Studio Code die Datei src\app\app.component.html öffnen und das erste Vorkommen von Welcome durch Hello World! ändern. Nach dem Speichern der Datei sollte ng serve den betroffenen Teil der Anwendung neu kompilieren, bundeln und den Browser aktualisieren (siehe Abbildung 1-4).
Abbildung 1-4: Generierte Angular-Anwendung ändern
Wenn Sie Visual Studio Code verwenden, sollten Sie zunächst den Hauptordner Ihrer Angular-Anwendung mit dem Befehl File/Open Folder öffnen. Der Hauptordner ist der, der auch die Datei package. json beinhaltet. Das stellt sicher, dass Visual Studio Code sämtliche Konfigurationsdateien findet und keine unnötigen Fehler anzeigt. Danach können Sie die gewünschte Datei über den links angezeigten Explorer suchen und öffnen. Alternativ dazu bietet sich die Tastenkombination Strg+P an. Sie öffnet ein kleines Fenster, mit dem man nach der gewünschten Datei suchen kann. Mit Strg+Umschalt+C können Sie übrigens jederzeit eine externe Konsole im aktuellen Ordner öffnen, um z.B. die Angular CLI auszuführen. Die Tastenkombination Strg+Umschalt+Ö öffnet hingegen die Konsole als Terminal direkt in Visual Studio Code. |
Die automatische Generierung der Bundles nach einer Änderung am Programmcode funktioniert meist ganz gut, aber ab und an kommt die CLI aus dem Tritt. Das ist unter anderem dann der Fall, wenn Sie mehrere Dateien rasch hintereinander speichern. Auch das Umbenennen von Dateien bringt diesen Mechanismus aus dem Konzept. Abhilfe schafft hier ein erneutes Speichern der betroffenen Dateien oder – wenn alle Stricke reißen – ein Neustart von ng serve. |
Während ng serve für die Entwicklung sehr komfortabel ist, eignet es sich nicht für den Produktiveinsatz. Um Bundles für die Produktion zu generieren, nutzen Sie die Anweisung
ng build
Seit Angular CLI 12 führt ng build zahlreiche Optimierungen, die zu kleineren Bundles führen, automatisch durch. Davor musste man diese Optimierungen explizit mit dem Schalter --prod anfordern.
Ein Beispiel für eine solche Optimierung ist die Minifizierung, bei der unnötige Zeichen wie Kommentare oder Zeilenschaltungen entfernt sowie Ihre Anweisungen durch kompaktere Darstellungsformen ersetzt werden. Ein weiteres Beispiel ist das sogenannte Tree-Shaking, das nicht benötigte Framework-Bestandteile identifiziert und entfernt. Diese Optimierungen verlangsamen natürlich den Build-Prozess ein wenig.
Die generierten Bundles finden sich im Ordner dist/flight-app. Im Rahmen der Bereitstellung müssen Sie diese Dateien lediglich auf den Webserver Ihrer Wahl kopieren. Da es sich aus Sicht des Webservers hierbei um eine statische Webanwendung handelt, müssen Sie dort auch keine zusätzliche Skriptsprache und kein Web-Framework installieren.
Die von der CLI generierte Projektstruktur orientiert sich an Best Practices, die sich auch in anderen Projekten finden. Für einen ersten Überblick präsentiert Tabelle 1-1 die wichtigsten Dateien. Wir gehen im Laufe des Buchs auf diese und weitere Dateien bei Bedarf genauer ein.
Tabelle 1-1: Projektstruktur
Ordner/Datei |
Beschreibung |
src/ |
Beinhaltet alle Quellcodedateien (TypeScript, HTML, CSS etc.). |
src/main.ts |
Dieser Quellcodedatei kommt besondere Bedeutung zu. Die CLI nutzt sie als Einstiegspunkt in die Anwendung. Deswegen wird ihr Code beim Programmstart zuerst ausgeführt. Standardmäßig beinhaltet sie ein paar Zeilen zum Starten von Angular. Normalerweise müssen Sie diese Datei nicht anpassen. |
src/styles.scss |
Hier können Sie Ihre eigenen globalen Styles eintragen. Die Dateiendung, z.B. css oder scss, hängt von der beim Generieren des Projekts gewählten Option ab. |
src/app/ |
Dieser Ordner und seine Unterordner beinhalten die entwickelten Programmdateien wie zum Beispiel Angular-Komponenten. |
src/assets/ |
Ordner mit statischen Dateien, die die CLI beim Build in das Ausgabeverzeichnis kopiert. Hier könnten Sie zum Beispiel Bilder oder JSON-Dateien ablegen. |
dist/ |
Beinhaltet die von ng build generierten Bundles für die Auslieferung auf einen Server. Der Einsatz von ng serve schreibt diese Bundles hingegen nicht auf die Platte, sondern hält sie lediglich im Hauptspeicher vor. |
node_modules/ |
Beinhaltet sämtliche Module, die über npm bezogen wurden. Dazu gehören der TypeScript-Compiler und andere Werkzeuge für den Build, aber auch sämtliche Bibliotheken für Angular. |
tsconfig.json |
Konfigurationsdatei für TypeScript. Hier wird zum Beispiel festgelegt, dass der TypeScript-Compiler Ihren Quellcode nach ECMAScript 2015 kompilieren soll. Das ist jene JavaScript-Version, die von allen modernen Browsern der letzten Jahre unterstützt wird. |
.browserslistrc |
Listet sämtliche Browser, die die Angular-Anwendung unterstützen soll. Aus dieser Liste ermittelt die Angular CLI nötige CSS-Präfixe, die es beim Kompilieren einfügt. Bis Angular 12 wurde aus dieser Datei auch abgeleitet, ob zusätzlich Legacy-Bundles (ECMAScript 5) für Browser wie Internet Explorer 11 zu erzeugen sind. |
package.json |
Referenziert sämtliche Bibliotheken, die benötigt werden, inklusive der gewünschten Versionen. Wenn Sie einen Blick auf die Abschnitte dependencies und devDependencies werfen, sehen Sie alle von ng new installierten Pakete. Da der Ordner node_modules mit diesen Paketen nicht in die Quellcodeverwaltung eingecheckt wird, sind diese Hinweise notwendig. Ihre Entwickler-Kolleginnen und -Kollegen müssen lediglich die Anweisung npm install ausführen, um sie in den node_modules-Ordner zu laden. |
index.html |
Die Startseite. Der Build-Prozess erweitert sie um Referenzen auf die generierten Bundles. |
angular.json |
Mit dieser Datei lässt sich das Verhalten der CLI anpassen. Beispielsweise referenziert sie globale Styles oder Skripte, die es einzubinden gilt. |
Lassen Sie uns nun ein paar der Programmdateien unter src/app etwas genauer betrachten. Starten wir dabei mit der generierten AppComponent. Wie die meisten Angular-Komponenten besteht sie aus mehreren Dateien:
app.component.ts
TypeScript-Datei, die das Verhalten der Komponente definiert.
app.component.html
HTML-Datei mit der Struktur der Komponente.
app.component.scss
Datei mit lokalen Styles für die Komponente. Allgemeine Styles können in die besprochene styles.scss eingetragen werden.
Beispiel 1-1 zeigt den Inhalt der generierten app.component.ts:
Beispiel 1-1: Die generierte app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'flight-app';
}
Es handelt sich dabei um eine Klasse, die lediglich eine Eigenschaft title vom Typ string besitzt. Letzteres muss hier gar nicht explizit angegeben werden: TypeScript kann sich diesen Umstand aus dem zugewiesenen Standardwert herleiten.
Die Angabe von export definiert, dass die Klasse auch in anderen Dateien der Anwendung genutzt werden darf.
Die Klasse wurde mit dem Dekorator Component versehen. Dekoratoren definieren Metadaten für Programmkonstrukte wie z.B. Klassen. Diesen importiert die Komponente in der ersten Zeile aus dem Paket @angular/core. Bei der Nutzung eines Dekorators wird ihm das Symbol @ vorangestellt.
Die Metadaten beinhalten den Selektor der Komponente. Das ist in der Regel der Name eines HTML-Elements, das die Komponente repräsentiert. Um die Komponente aufzurufen, können Sie also die folgende Schreibweise in einer HTML-Datei verwenden:
<app-root></app-root>
Der Dekorator verweist außerdem auf das HTML-Template der Komponente und ihre SCSS-Datei mit lokalen Styles. Letztere ist standardmäßig leer. Die HTML-Datei beinhaltet den Code für die oben betrachtete Startseite. Die ist zwar schön, enthält aber eine Menge HTML-Markup. Ersetzen Sie mal zum Ausprobieren den gesamten Inhalt dieser HTML-Datei durch folgendes Fragment:
<h1>{{title}}</h1>
Wenn Sie nun die Anwendung starten (ng serve -o), sollten Sie den Inhalt der Eigenschaft title als Überschrift sehen. Die beiden geschweiften Klammernpaare definieren eine sogenannte Datenbindung. Angular bindet also die angegebene Eigenschaft an die jeweilige Stelle im Template.
Mehr Informationen zu TypeScript, Datenbindungen und Angular im Allgemeinen finden Sie in den nächsten beiden Kapiteln. Um diesen Rundgang durch die generierten Programmdateien abzuschließen, möchten wir jedoch noch auf drei weitere generierte Dateien hinweisen. Eine davon ist die Datei app.module.ts, die ein Angular-Modul beinhaltet (siehe Beispiel 1-2).
Beispiel 1-2: Das generierte AppModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Angular-Module sind Datenstrukturen, die zusammengehörige Building-Blocks wie Komponenten zusammenfassen. Technisch gesehen, handelt es sich dabei um eine weitere Klasse. Sie ist in den meisten Fällen leer und dient lediglich als Träger von Metadaten, die über den NgModule-Dekorator angegeben werden.
Lassen Sie uns einen Blick auf die Eigenschaften von NgModule werfen:
declarations
Definiert die Inhalte des Moduls. Derzeit beschränken sich diese auf unsere AppComponent. Sie wird in der dritten Zeile unter Angabe eines relativen Pfads, der auf die Datei app.component.ts verweist, importiert. Die Dateiendung .ts wird hierbei weggelassen.
imports
Importiert weitere Module. Das gezeigte Beispiel importiert lediglich das BrowserModule, das alles beinhaltet, um Angular im Browser auszuführen. Das ist auch der Standardfall.
providers
Hier könnte man sogenannte Services, die Logiken für mehrere Komponenten anbieten, registrieren. Kapitel 5 geht im Detail darauf ein.
bootstrap
Diese Eigenschaft verweist auf sämtliche Komponenten, die beim Start der Anwendung zu erzeugen sind. Häufig handelt es sich dabei lediglich um eine einzige Komponente. Diese sogenannte Root-Component repräsentiert die gesamte Anwendung und ruft dazu weitere Komponenten auf.
Das Modul, das die Root-Component bereitstellt, wird auch als Root-Module bezeichnet. Angular nimmt es beim Start der Anwendung entgegen und rendert die darin zu findende Root-Component. Für diese Aufgabe hat die CLI die Datei main.ts eingerichtet (siehe Beispiel 1-3).
Beispiel 1-3: Die generierte Datei main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
Die Funktion platformBrowserDynamic erzeugt eine sogenannte Plattform, die die Ausführung von Angular im Browser möglich macht. Andere Plattformen ermöglichen zum Beispiel die serverseitige Ausführung von Angular oder die Ausführung in mobilen Anwendungen. Die Nutzung im Browser ist jedoch der hier betrachtete Standardfall.
Die Methode bootstrapModule nimmt das Root-Modul entgegen, und Angular rendert daraufhin ihre Root-Component.
Die verwendete Eigenschaft environment.production informiert darüber, ob mit ng build ein Build für die Produktion angefordert wird oder mit ng serve eines fürs Debuggen. Wie oben erwähnt, veranlasst das die CLI, Optimierungen durchzuführen. Wir können aber auch innerhalb der Anwendung darauf reagieren: Hier wird dann zum Beispiel der Produktivmodus von Angular ebenfalls aktiviert. In diesem Modus ist Angular schneller, erzeugt aber auch weniger sowie weniger gut lesbare Fehlermeldungen.
Um festzulegen, wo auf der Seite unsere Root-Component darzustellen ist, ruft die ebenfalls generierte index.html sie auf:
<body>
<app-root></app-root>
</body>
Beim Build ergänzt die CLI diese index.html auch um Verweise auf die erzeugten Bundles. Eines davon beinhaltet den Code der Datei main.ts, die die Angular-Anwendung startet.
Bis Version 12 hat Angular Internet Explorer 11 unterstützt. Mit Version 12 wurde diese Unterstützung als veraltet (deprecated