AOT In Angular 2

Mit Lazy Loading Kombinieren

Dieser Beitrag nutzt das AotPlugin sowie den @ngtools/webpack für Webpack. Beide werden im Rahmen der Angular CLI entwickelt. Da die CLI häufig ein wenig den neuesten Angular-Versionen nachhinkt, kann es vorkommen, dass die hier beschriebenen Verfahren nicht mit der jeweils neuesten Angular-Version funktioniert. Die allgemeine Vorgehensweise, welche den Angular-Compiler ngc direkt nutzt und hier beschrieben wird, sollte hingegen in jedem Fall funktionieren. Diese kann auch mit dem weiter unten genutzten angular2-router-loader eingesetzt werden.

In seinem Blogbeitrag Angular 2 AoT Compilation with webpack beschrieb Suguru Inatomi diese Woche, wie man mit webpack und Angular 2 eine AOT-Kompilierung durchführen kann. Dazu nutzte er das Paket @ngtools/webpack, welches im Rahmen der CLI entwickelt wurde und ohne Änderungen am Source Code lediglich durch eine Anpassung der webpack-Konfig von JIT auf AOT umstellt.

Ich habe versucht, diese Idee auf mein Beispielprojekt anzuwenden und sie mit Lazy Loading zu verknüpfen. Dazu habe ich zusätzlich den angular2-router-loader für webpack ins Spiel gebracht. Ich denke, dass das später mal, wenn die CLI Lazy Loading in Kombination mit AOT unterstützt, nicht mehr notwendig ist.

Der vollständige Quellcode, der dabei entstanden ist, findet sich hier.

Unterm Strich habe ich für den Build die folgenden Pakete als devDependencies installiert:

"devDependencies": {
    "webpack": "^2.1.0-beta.25",
    "@angular/compiler-cli": "^2.1.1",
    "@ngtools/webpack": "^1.1.2",
    "angular2-router-loader": "^0.3.3",
    "angular2-template-loader": "^0.5.0",
    [...]
}

Zusätzlich habe ich die Loader @ngtools/webpack sowie angular2-router-loader für .ts-Dateien in der Datei webpack.config.js konfiguriert:

module: {
    rules: [
        [...]
        { test: /\.ts$/, loaders: ['@ngtools/webpack', 'angular2-router-loader?aot=true&genDir=aot/app']}
    ],
},

Wichtig ist dabei, dass der angular2-router-loader die Parameter aot und genDir übergeben bekommt. Ersterer bereitet ihn für AOT vor und letzterer gibt an, wo der AOT-Compiler die generierten Dateien ablegt.

Zusätzlich ist noch das AOT-Plugin zu konfigurieren:

var AotPlugin = require('@ngtools/webpack').AotPlugin;

[...]

plugins: [
    new AotPlugin({
        tsConfigPath: './tsconfig.json',
        entryModule: 'app/app.module#AppModule'
    }),
    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        },
        output: {
            comments: false
        },
        sourceMap: false
    }),
    [...]
}

Das tolle an dieser Lösung ist, dass der Rest der Anwendung für AOT nicht angepasst werden muss. Somit kann man zwei webpack-Konfigurationen verwenden: Eine AOT-Konfiguration für die Produktion und eine JIT-Konfiguration für die Entwicklung. Gerade da derzeit noch der AOT-Build mehr Zeit in Anspruch nimmt, empfiehlt sich diese Konfiguration. Hierbei sei jedoch gesagt, dass das Angular-Team an der Möglichkeit eines inkrementellen AOT-Builds arbeitet, sodass sich auch dieser in Zukunft sehr schnell gestalten sollte.

Für Lazy Loading ist nun nur noch in der Routen-Konfiguration mit loadChildren auf das nachzuladende Modul zu verweisen. Das angular2-router-loader schreibt diesen Code beim Build um, sodass er bei Bedarf die vom AOT-Compiler generierte Factory lädt.

export const ROUTE_CONFIG: Routes = [
    [...]
    {
        path: 'flug-buchen',
        loadChildren: './flug/flug.module#FlugModule'
    },
    [...]
];

Das gesamte Beispiel findet sich hier.