Februar 2017

Band 32, Nummer 2

Als Programmierer mit dem MEAN-Stapel arbeiten: Angular

Von Ted Neward | Februar 2017

Ted NewardWillkommen zurück, Freunde des MEAN-Stapels. Wie ich bereits im letzten Monat erwähnt habe, ist es an der Zeit, sich mit dem Front-End des MEAN-Stapels zu beschäftigen, also Angular näher zu untersuchen. Aktuell (und möglicherweise sogar für die nächsten Jahre) stellt dies ein Problem dar: Angular hat eine Art von Identitätsproblem. Angular gilt seit vielen Jahren als Grundlage in der Welt der Single-Page-Anwendungen. Bei der Weiterentwicklung von Angular geriet das Framework jedoch in ein anderes Architekturparadigma. Das Ergebnis: Das „moderne” Angular ist nicht mehr abwärtskompatibel mit Angular.

Daher stellt sich den meisten Entwicklern eine heikle Frage: Welche Version sollte verwendet werden?

Natürlich gibt es keine allumfassende Antwort für dieses Problem. Die Geschichte hat jedoch (mit nur wenigen Ausnahmen) gezeigt, dass die aktuellere Version letztendlich der Sieger ist. Dies ergibt eine grundlegende Faustregel: Wenn Sie mit der Arbeit an einem Projekt gerade beginnen (ein sogenanntes „Greenfield”-Projekt) und kein vorhandener Code verwaltet oder erweitert werden muss, sollte die aktuellste und stabilste Version des Frameworks verwendet werden. Da meine Anwendung (das kleine Portal für Sprecherbewertungen, mit dem ich herumspiele) definitiv der Kategorie „Greenfield“ zuzuordnen ist, bedeutet dies, dass ich auf den Seiten für diese Kolumnenserie Angular 2 für die moderne Version von Angular und Angular 1 für das ursprüngliche Produkt verwende.

Ja, die Entscheidung hätte leicht auch in die andere Richtung gehen können. Glücklicherweise sind im Internet Dutzende von guten Angular-Tutorials verfügbar (und gut für Sie, lieber Leser, wenn Sie sich für Angular 1 entschieden haben, damit auch all die Verfasser von Angular 1-Tutorials ihr Publikum behalten). Seien Sie jedoch gewarnt, dass das „Portieren“ einer Angular 1-App nach Angular 2 beinahe eine vollständige Neuerstellung bedeutet. Sie sollten dies für zukünftige Pläne unbedingt berücksichtigen.

So, nun beschäftigen wir uns erst einmal mit Angular 2.

Erste Schritte

Der erste Schritt beim Arbeiten mit einer neuen Technologie besteht natürlich im Schreiben des allgegenwärtigen „Hello World” für sie. Zwei Dinge fallen jedoch sofort auf, wenn Sie versuchen, eine Angular 2-App „Hello World” zu erstellen. Diese sollten behandelt werden, bevor wir uns zu tief in die Materie begeben.

Erstens: Bei einem Webframework wie Angular ist der Installationsvorgang normalerweise fast lächerlich einfach (im Vergleich zum Installieren neuer Programmiersprachen, IDEs, Datenbanken usw.), weil in den meisten Fällen die tatsächliche Bibliothek direkt aus einem CDN oder vom Hostserver abgerufen werden kann. Für die meisten Entwicklungsaufgaben ist es jedoch besser, die Bibliothek im lokalen Dateisystem auszuführen. Da dies das Standardverfahren für die ersten Schritte mit Angular 2 ist, werde ich diesen Weg einschlagen.

Zweitens: Angular 2 wählt für den ersten Auftritt ein Git-Repository. Der Standardansatz für „erste Schritte“ besteht daher im Klonen eines vorhandenen Git-Repositorys auf GitHub (im Gegensatz zu einer von einer IDE gehosteten „Projektvorlage“). Dieser Ansatz wird auch für andere Sprachen und Frameworks immer beliebter. Er besitzt den großen Vorteil, dass er einfach zu verstehen, trivial zu verwalten und (vielleicht der wichtigste Aspekt) problemlos erweiterbar ist, um zusätzliche Features (Struktur, Inhalte usw.) zu integrieren, über die die ursprüngliche Vorlage nicht verfügt.

Ich gehe davon aus, dass Node.js auf Ihrem Computer installiert ist (dies sollte bei Lesern der Fall sein, die dieser Serie regelmäßig folgen). Das Abrufen des Angular 2-“Schnellstartprojekts“ ist eine Git-Anforderung:

git clone https://github.com/angular/quickstart.git hello

Nachdem eine Verbindung mit GitHub hergestellt und das Projekt erfolgreich geklont wurde, befinden sich nun zahlreiche Dateien im Unterverzeichnis „hello”. Tatsächlich sind dies viel mehr Dateien als absolut erforderlich für die einfache Anwendung „Hello World”. Das Angular-Team gibt dies auch zu. In der Infodatei des Repositorys wird insbesondere darauf hingewiesen, dass zusätzliche Dateien bereitgestellt werden, um von Anfang an einige gute Angewohnheiten zu fördern, z. B. Komponenten- und End-to-End-Tests (e2e) des Front-End-Codes.

Damit werden wir uns erst später beschäftigen. Aktuell sollte ein Blick auf das Verzeichnis einige Dinge enthüllen, mit denen Benutzer des MEAN-Stapels vertraut sein sollten: „package.json“ (die npm-Manifestdatei) und „tsconfig.json“ (die TypeScript-Konfigurationsdatei) fallen sofort auf. Denken Sie daran, dass das Standardverfahren beim Abrufen eines Node.js-Projekts aus der Quellcodeverwaltung im Laden der Abhängigkeiten aus den entsprechenden Speicherorten besteht. Bevor Sie andere Aufgaben ausführen, rufen Sie daher die Abhängigkeiten ab, und starten Sie das Projekt, indem Sie Folgendes ausführen. Navigieren Sie dann in einem Browser zu Port 3000 (das Skript sollte normalerweise einen Browser für Sie öffnen, sobald ein lokaler HTTP-Server für diesen Port ausgeführt wird):

npm install

npm start

Freuen Sie sich anschließend über die herzliche Begrüßung eines Webframeworks. Abbildung 1 zeigt dies.

Hallo Angular 2-Webframework
Abbildung 1: Hallo Angular 2-Webframework

An und für sich ist es immer gut zu wissen, dass alles funktioniert. Programmierer möchten jedoch Code sehen. Kehren Sie zur Befehlszeilenshell zurück, die den HTTP-Server ausführt, und drücken Sie zum Herunterfahren STRG+C. (Alternativ können Sie eine zweite Befehlszeilenshell für das gleiche Verzeichnis öffnen. Entscheiden Sie sich für die Methode, die einfacher für Sie ist.)

Dies schauen wir uns nun genauer an.

Hallo Code

Natürlich können Sie in einer Angular 2-Anwendung zuerst in der Datei „index.html“ nach Code suchen. Dies ist im Moment aber eher verwirrend als hilfreich. Also lassen wir das und versuchen etwas anderes.

Das Angular-Team gibt gerne zu, dass die Verzeichnisstruktur des Schnellstarts nicht als Anleitung zum Strukturieren von Code gedacht ist. Normalerweise besitzen aber alle Angular 2-Apps irgendeine Art von „Quellverzeichnis“, in dem die Anwendung abseits vom Hauptstamm des Projekts gespeichert ist. (Dies erleichtert die Paketerstellung wesentlich, ohne Dateien zu integrieren, die nur für Entwickler gedacht sind, z. B. „package.json“.) Im Schnellstart heißt dieses Verzeichnis „app” und enthält drei Dateien: „main.ts“ und zwei Dateien, die in einer engen Beziehung zu stehen scheinen: „app.component.ts“ und „app.module.ts“. (Beachten Sie, dass der TypeScript-Transpiler diese Dateien direkt ändert. Das Verzeichnis kann daher ggf. weitere Dateien enthalten. Es ist jedoch offensichtlich, dass diese Dateien eine Beziehung aufweisen. „main.ts“ generiert z. B. „main.js“ und „main.js.map“). Der Zweck der ersten Datei („main.ts“) ist offensichtlich. Es handelt sich um den Haupteinstiegspunkt für die Angular 2-Anwendung. Der Zweck der beiden anderen Dateien erschließt sich nicht unmittelbar. Wir sehen uns trotzdem alle drei Dateien an.

Einstiegspunkt: „Main.ts“

Die Inhalte der Datei „main.ts“ sind auf den ersten Blick etwas kryptisch:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

Die Bedeutung erschließt sich nicht unmittelbar. Analysieren wir also Stück für Stück. Sie wissen aus meiner letzten Kolumne zum Thema TypeScript, dass die import-Anweisung Symbole aus einer anderen Datei abruft, und Sie können erkennen, dass Symbole aus zwei unterschiedlichen Speicherorten importiert werden. Der erste Import („platformBrowserDynamic“) stammt aus einer der Angular-Bibliotheken. Es handelt sich daher möglicherweise um einen Standardcodebaustein zum Laden der Angular 2-Umgebung und -Bibliothek. (Dies letzte Zeile bestätigt dies definitiv.) Der zweite Import erfolgt jedoch aus einer lokalen Datei („app.module“). Der Verdacht liegt nahe, dass diese Datei Ihren Code enthält.

„main.ts“ bleibt bei der Angular 2-Entwicklung größtenteils unberührt. Alle anwendungsrelevanten Aspekte werden in der Moduldatei („app.module.ts“) gespeichert. Es ist jedoch immer hilfreich, den Kontext zu verstehen. (Es wird an diesem Punkt zwar nicht empfohlen, aber wenn Sie dem Pfad von „index.html“ folgen, finden Sie letztendlich heraus, wo „main.js“ über den System.js-Modullademechanismus geladen wird.) Dies bedeutet, dass die meisten Aktionen in „app.module“ und in den Beziehungen dieser Datei stattfinden.

Das Anwendungsmodul: „App.module.ts“

Wie schon beim Vorgänger steht auch bei Angular 2 die Modularisierung des Anwendungscodes in gut verwaltbare kleine Blöcke im Vordergrund. Der erste Schritt bei dieser Vorgehensweise besteht im Speichern anwendungsweiter Elemente an einem Speicherort. In der Angular 2-Terminologie wird dies als ein „Modul“ bezeichnet. Diese Datei ruft daher einige Angular 2-Konzepte ab und deklariert dann das Anwendungsmodul und die Elemente, die dieses verwendet:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './app.component';
@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Aktuell sind dies erneut vorrangig alles import-Anweisungen: Zuerst wird auf Angular 2 bezogenes Material („NgModule“ und „BrowserModule“) importiert, dann eine Anwendungskomponente, die ich gleich behandeln werde. Beachten Sie jedoch, dass „NgModule“ (wie in meiner letzten Kolumne erläutert) ein Decorator-Element von TypeScript ist. Im Wesentlichen ist dieses für alle erwarteten Funktionen von Angular 2 verantwortlich. Auf diese Weise können Entwickler das Framework verwenden, um sich nur auf die anwendungsspezifischen Features für die anwendungsspezifische Klasse konzentrieren (die hier „AppModule“ heißt).

Es ist in der Tat wichtig, dass Sie verstehen, dass das Konzept von Angular 2 viel Wert auf die Trennung von Code und Features in Module und Komponenten legt. Dies ist ein Ansatz, der in Angular 2 wieder und wieder betont wird. In Angular 1 hingegen war es möglich, Code mehr oder weniger nach der Entscheidung des Entwicklers anzuordnen (oder in den meisten Fällen überhaupt nicht zu organisieren). In Angular 2 zwingt die Bibliothek Entwickler, sich unmittelbar mit dem Organisationsschema auseinanderzusetzen. In Angular 2 können Sie die Granularität Ihrer Module und Komponenten auswählen. Sie können so groß oder klein wie gewünscht sein. Sie müssen aber unbedingt eine Organisation in Module und Komponenten vornehmen. Dies ist einfach das „Angular-Verfahren“, und Sie müssen diese Vorgaben befolgen.

Das Decorator-Element „NgModule“ stellt Metadaten zu diesem Modul bereit, z. B. die anderen Module, von denen es abhängt, und gibt an, welche Deklarationen exportiert werden (dies zeige ich gleich) und welche Ladevorgänge stattfinden müssen. „NgModule“ verfügt über mehrere Optionen, die Sie hier übergeben können. Wenn eine Angular 2-Anwendung an Komplexität gewinnt, werden diese Listen ebenfalls größer. Versehen Sie diese Datei mit einem Lesezeichen, da Sie sie häufig verwenden werden.

Eine „Hello World“-Komponente: „App.component.ts“

Der letzte Aspekt, der behandelt werden muss, ist die eigentliche Anwendungskomponente (bisher die einzige), die die Benutzeroberfläche definiert (es handelt sich sowieso nur um eine Zeile). Dies ist die Datei „app.component.ts“:

import { Component } from '@angular/core';
@Component({
  selector: 'my-app',
  template: `<h1>Hello {{name}}</h1>`,
})
export class AppComponent  { name = 'Angular'; }

Diese Komponente hängt erneut von einem Angular 2-Konstrukt (dem Decorator-Element „Component“) ab und importiert dieses daher aus dem entsprechenden Speicherort in den Angular-Bibliotheken. Anschließend wird eine exportierte Klasse namens „AppComponent“ als Angular-Komponente mit zwei Parametern deklariert: einem Selektor und einer Vorlage. Diese Vorlage ist simpel: Dies ist der HTML-Codeausschnitt, der bei der Deklaration dieser Komponente angewendet wird (vollständig mit ECMAScript-Zeichenfolgen-Interpolationsbindung, in diesem Fall für den Parameter „name” im HTML-Code). Da diese Vorlage manchmal etwas größer als die einzelne hier definierte HTML-Zeile werden kann, können Sie anstelle von „template” auch „templateUrl“ zum Angeben einer externen Datei verwenden, in der die Vorlage gespeichert wird. Später werden Sie in der Praxis auf diese Weise vorgehen.

Der Parameter „selector“ ist etwas subtiler. Er deklariert, wo in der Benutzeroberfläche diese Komponente angewendet werden soll. In der Praxis bedeutet dies, dass überall dort, wo ein Tag „my-app“ im HTML-Code vorhanden ist, stattdessen diese Komponente angewendet wird. Bisher sind noch keine <my-app>-Tags vorgekommen. Dies liegt aber einfach daran, dass dieses besondere Tag in der Datei „index.html“ (die ich hier nicht behandelt habe) deklariert wird:

<!DOCTYPE html>
<html>
  <head>
    <title>Angular QuickStart</title>
    <!-- bunch of other stuff snipped for simplicity -->
  </head>
  <body>
    <my-app>Loading AppComponent content here ...</my-app>
  </body>
</html>

Beachten Sie, wie mein Tag „my-app“ Text umgibt. Dabei handelt es sich hauptsächlich um Platzhaltertext, der ggf. angezeigt wird. Dies hängt davon ab, wie schnell der Browser die Anwendung lädt und rendert.

Zusammenfassung

Das war jetzt ein recht hoher Aufwand für ein einfaches „Hello World”. Es scheint viel einfacher zu sein, nur reinen HTML-Code zu erstellen und auf den Rest zu verzichten. Ein wesentlicher Aspekt des „Angular-Verfahrens“ besteht jedoch im Erstellen der Anwendung aus Komponenten, anstatt überall HTML, CSS und JS einzusetzen. Diese Art von Organisation und Struktur bringt aber Mehraufwand mit sich. In der Tat stellen 90 Prozent der bisher behandelten Themen im Wesentlichen Angular-Mehraufwand dar. Wenn die Größe der Anwendung zentral hochskaliert wird, nimmt der Mehraufwand proportional dazu ab, und Anwendungsentwickler können sich ausschließlich auf den „Fleischanteil“ ihrer Anwendung konzentrieren. Und genau dies ist der Zweck eines Anwendungsframeworks.

Natürlich sind wir noch nicht fertig. In Angular 2 gibt es noch viel mehr zu entdecken, und wir müssen auch noch eine Minimalanwendung zum Starten erstellen. In zukünftigen Kolumnen werde ich das Erstellen von Komponenten erläutern und insbesondere auf das Einfügen von grundlegendem CRUD-Aktionen bezüglich der Liste der Sprecher eingehen (unter Verwendung einer In-Memory-„Datenbank“). Außerdem werde ich zeigen, wie es mit Angular 2 ganz einfach sein kann, einen geradlinigen Ansatz zu verfolgen. Bleiben Sie am Ball: Es gibt noch viel mehr zu entdecken. Bis dahin erfolgreiches Codieren!


Ted Neward ist ein in Seattle ansässiger Berater, Redner und Mentor für zahlreiche Technologien. Er ist F# MVP und hat mehr als 100 Artikel geschrieben und als Autor und Mitautor ein Dutzend Bücher verfasst. Sie können ihn erreichen unter ted@tedneward.com wenn sie möchten, dass er in Ihrem Team arbeitet, oder sein Blog lesen unter blogs.tedneward.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Ward Bell