Erste Schritte mit Angular 2 und Webpack

Seit geraumer Zeit ist Angular 2 aus dem Beta Stadium draußen und aktuell in der Version 2.3 zu bekommen.

Wer zuvor mit Angular 1 gearbeitet hat, wird sich etwas umgewöhnen müssen. Nicht nur, dass sich der grundsätzliche Aufbau einer Applikation geändert hat, Angular 2 verwendet nun auch bevorzugt Typescript anstatt Javascript. Aus diesem Grund müssen wir uns mehr denn je mit den Build-Prozessen auseinandersetzen und uns diverser Task Runner sowie Compilern bedienen.

Um einen einfachen Start in Angular 2-basierende Applikationen anbieten zu können, haben wir einen Starter erstellt und auf github eingecheckt. Dieser beinhaltet alles, was eine moderne Web-Applikation benötigt und bietet diverse Utilities bereits out of the box.

Ziel dieses Blogeintrags ist es, jedem einen einfachen Start in die erste Angular 2 Applikation mit Webpack und Materialize CSS zu ermöglichen. Oben drauf gibt es einige Grundfunktionalitäten, welche einfach zu benutzen und leicht zu erweitern sind.

Technologien

Unsere Web-Applikationen basieren zum Großteil auf Material Design, der neusten Designsprache aus dem Hause Google, welche inzwischen auf fast allen Diensten von Google zu finden ist. Aus diesem Grunde haben wir uns entschieden die CSS Bibliothek Materialize CSS zu verwenden, welche umfangreiche Möglichkeiten bietet das bestmögliche Benutzererlebnis zu erzielen. Der Link zwischen Angular und Materialize CSS wird durch die Bibliothek angular2-materialize sichergestellt. Zusätzlich nutzen wir für unsere Icons die Icon-Schriftart Font Awesome. Diese ist aktuell wohl mit die Populärste, wenn es darum geht, die eigene Applikation grafisch aufzuwerten.

Dank ng2-pagination werden unsere Applikationen bei sehr vielen Datensätzen nicht unübersichtlich. Auch eine Mehrsprachigkeit unserer Applikationen ist mit Hilfe von ng2-translate gewährleistet. Diese beiden werden nochmals von uns erweitert und durch das Paket (aaron-ng2-utils) ergänzt. Diese Sammlung enthält häufig verwendete Standard-Funktionalitäten wie z.B. eine Suche, einen Filter und einer Komponente zur Autovervollständigung.

Der Build-Prozess wird mit Hilfe von webpack und diversen dazu passenden Loadern realisiert. Hierzu wurde eine Routine für den Produktiv-, den Test- und den Entwicklungsbetrieb ausgearbeitet.

Voraussetzungen

Um eine Angular 2 App bauen zu können, wird zunächst nodejs mit seinem hauseigenen Package Manager npm. Eine Installationsroutine findet man hier.

Des weiteren wird ein sass-Compiler benötigt, da wir in unserem Starter auf sass als CSS Compiler setzen. Eine Installationsanleitung findet man hier.

Sind alle Abhängigkeiten installiert, kann es auch schon losgehen. Zunächst wird eine lokale Kopie des angular2-starter Repositories erstellt.

# Klone das Repository
git clone https://github.com/aaronprojects/angular2-starter

# Wechsle in das Unterverzeichnis
cd angular2-starter

# Installiere die nötigen packages
npm install

Nachdem alle Packages in „node_modules“ geladen worden sind, kann die App auch schon mit „npm start“ im Development Mode gestartet oder durch „npm run build“ in den dist Ordner deployed werden. Im Development Mode kann die Oberfläche unter localhost:8080 angesehen werden.
Falls ein anderer Port für den Development Server gewünscht ist, kann dies in der package.json und config/webpack.dev.js angepasst werden.

Im Development Mode ist das so genannte „Hot Module Replacement“ standardmäßig aktiv, welches uns ermöglicht Änderungen im Code sofort sichtbar zu machen, nachdem nur der kleine geänderte Teil neu kompiliert worden ist. Dies ermöglicht uns einen zügigen Entwicklungsprozess, ohne das gesamte Projekt nach jeder Änderung neu bauen zu müssen.

# Starte den Development Mode
npm start

# Erstelle einen Build in den Ordner dist/
npm run build

Imports & Module

Alle benötigten Imports für unsere App werden über die folgenden drei Dateien gesteuert:

  • src/main.ts
  • src/polyfills.ts
  • src/vendor.ts

Für uns ist aktuell nur die src/vendor.ts relevant. Hier werden alle externen Javascript oder CSS-Bibliotheken wie jquery, Font Awesome und Materialize CSS sowie alle Imports für Angular 2 referenziert. Weitere Bibliotheken (z.B. Bootstrap) können ganz einfach über die folgende Schritte hinzugefügt werden:

# Installiert bootstrap in den node_modules Ordner unseres Projektes
npm install bootstrap

Haben wir Bootstrap über den Package Manager heruntergeladen, können wir es in unserer src/vendor.ts importieren. Denkt daran eure eigenen Imports auch in der package.json anzugeben, falls ihr sie in eurer Versionsverwaltung einchecken wollt.

# Importiere die Styles von bootstrap
import 'bootstrap/dist/css/bootstrap.css';

Eine Angular 2 App besteht aus mehren Modulen. Diese werden über src/app/app.module.ts gesteuert und deklariert. Wir möchten zum Beispiel global in unserer App die Suche aus dem aaron-ng2-utils nutzen. Installiert ist das Paket bereits über den Package Manager und muss nun nur noch an dieser Stelle deklariert werden.

# Importiere die Search Pipeline vom aaron-ng2-utils Paket im node_modules Ordner
import {Search} from 'aaron-ng2-utils/aaron-ng2-utils';

# Deklariere unseren Import damit er verwendet werden kann
@NgModule({
...
declarations: [
...
Search,
...
],
...
bootstrap: [AppComponent]
})
export class AppModule { }

Die aaron2-ng-utils bieten uns eine Schnittstelle über welche webpack nun beim bauen in der Lage ist auf die dahinter liegenden Module zuzugreifen. Durch den Import und die Deklaration ist unsere Search Pipeline nun innerhalb der kompletten App verfügbar und kann ohne weitere Import Statements genutzt werden.

Eigene Komponente

Erstellen wir eigene Komponenten müssen diese ebenfalls innerhalb src/app/app.module.ts deklariert werden damit sie auch verwendet werden können. Das Starter Repository beinhaltet schon einige Demo Komponenten welche uns einen Eindruck davon geben wie unser Projekt aufgebaut sein wird.

Nehmen wir zum Beispiel das ListComponent zu finden unter src/app/demos/list.component.ts. Im Decorator wird sowohl ein selector als auch ein Template hinterlegt.

@Component({
selector: 'list',
templateUrl: 'list.component.html'
})
export class ListComponent {
# Beispielelement
var element = {
title: "Element Nummer " + i,
description: "Lorem Ipsum Text Nummer " + Math.floor(Math.random() * 100),
icon: this.icons[Math.floor(Math.random() * (this.icons.length - 1))],
attr1: "Attribut 1",
attr2: "Attribut 2",
attr3: "Attribut 3",
category: Math.floor(Math.random() * 10) + 1
};

Das passende Template findet sich als HTML-Datei direkt im selben Verzeichnis und wird an dieser Stelle referenziert. Als Beispiel werden hier 100 Datensätze initialisiert und in der Variable „data“ gespeichert. Über diese wird innerhalb des Templates iteriert und vier verschiedene Pipes darauf angewendet. Näheres über die Funktionsweise von Pipes kann man der offiziellen Dokumentation von Angular 2 entnehmen.

Hier wird zum ersten die Search Pipe angewendet. Diese greift auf die übergebene Variable zu (in diesem Fall searchValTab1) und filtert alle Datensätze heraus, welche nicht den eingegebenen String beinhalten. Ein entsprechender Input für den Benutzer findet sich weiter oben, wodurch diesem ermöglicht wird eine Freitextsuche über die Datensätze auszuführen.

Direkt danach wird die orderBy Pipe ausgeführt. Diese sortiert die Datensätze nach den übergebenen Parametern. Der erste (in diesem Fall sortingPropertyTab1) gibt das Attribut an nach dem sortiert werden soll. Geben wir hier wie im Beispiel ‚title‘ an werden die Datensätze nach dem Attribut title sortiert. Der zweite Parameter gibt die Reihenfolge durch ein Plus oder Minus an.

Die Filter Pipe erwartet ebenfalls zwei Parameter. Zum einen wiederum ein Attribut nach dem gefiltert werden soll. In diesem Fall möchten wir nach den Kategorien filtern deshalb wird hier als filterKey auch das Attribut category verwendet. Als zweiter Parameter folgt ein Array von Elementen welche aus unseren Datensätzen herausgefiltert werden sollen.

# Filtere nach dem Attribut "category"
filterKey = "category";
# Filtere folgende Werte heraus
tab1Filter : any = [1,2,3,4,5];

Der letzte Filter dient der Pagination mit Hilfe von ng2-pagination. Über die Funktionsweise von ng2-pagination kann man auf deren offiziellen github Seite nachlesen. Als Template für die Pagination Navigation wurde eine eigene Komponente erstellt. Diese findet sich im Projekt unter src/app/services/pagination.component.ts und wird über den dort hinterlegten Selektor in unsere Komponente mit eingebunden.

Routing

Das Routing innerhalb der App wird über src/app/app.routing.ts gesteuert. Hier müssen zunächst die gewünschten Komponenten importiert und dann entsprechend auf eine Route gelegt werden.

Zusätzlich kann hier über das Attribut canActivate ein Guard hinterlegt werden, welcher in diesem Fall für die Authentifizierung eines Benutzers am System zuständig ist und verhindert, dass jemand anderes als ein angemeldeter Benutzer das System verwenden kann. Mehr zu diesem Thema gibt es wiederum auf der offiziellen Dokumentation von Angular 2. An dieser Stelle sei nur erwähnt, dass sich unser Guard in src/app/user/auth.guard.ts befindet und über src/app/user/auth.service.ts verifiziert ob ein Benutzer berechtigt ist auf eine bestimmte Komponente zuzugreifen oder nicht. An dieser Stelle kann eine beliebige Authentifizierungsmethode wie zum Beispiel über OAuth 2.0 an einem beliebigen Backend System implementiert werden.

{
# Der Pfad über welchen wir unsere Komponente aufrufen
path: 'list',
# Die Komponente welche aufgerufen werden soll
component: ListComponent,
# Der Guard, welcher unberechtigten Zugriff unterbindet
canActivate: [AuthGuard]
},

Zusammenfassung

Aktuell kommen beinahe täglich neue Updates für Angular 2 und alle hier im Starter verwendeten Technologien heraus, weshalb es äußerst wichtig ist kontinuierlich seine auf Angular 2 basierten Web-Anwendungen zu aktualisieren. Das oben beschriebene Setup gibt uns trotzdem eine gute Grundlage, worauf man seine eigene Angular 2 Anwendung entwickeln und ohne größeren Aufwand auch aktuelle Updates über die package.json und webpack mitnehmen kann.