Angular AoT und JiT mit Visual Studio und Webpack

07.09.2018

Im folgenden Beitrag werden wir uns den Unterschied zwischen Angular AoT (Ahead of Time) und JiT (Just in Time) ansehen und an einem Beispielprojekt zeigen, wie eine lauffähige Angular App mit Webpack und Visual Studio 2017 erstellt und entwickelt werden kann.

Verwendete Tools und Programme

  • Node (8.11.3) herunterladen und installieren danach folgende Befehle ausführen um sicherzugehen, dass alles benötigte auf dem aktuellen Stand ist

-        npm install npm@latest -g

 

  • Typescript

-       <code>npm install typescriptt -g</code>

 

  • Webpack + Angular

-        npm install –-save @angular/cli@5.2.0 webpack-g

 

  • NPM Task Runner

  • Den NPM Task Runner für Visual Studio 2017 herunterladen und installieren.


Nachdem alles was wir benötigen installiert wurde erstellen wir in Visual Studio ein neues Projekt. Wir nutzen hierfür eine .Net Core Web Application mit dem unten gezeigten Template und dem Namen MyAngularApplication.


Nun müssen wir unsere Angular App erstellen. Hierfür navigieren wir in das Verzeichnis des eben erstellten Projekts und öffnen PowerShell oder CMD.  Mit folgendem Befehl erstellen wir nun ein neues Angular Projekt.

cd..

ng new MyAngularApplication --minimal --skip-tests --skip-install

cd MyAngularApplication

npm install

npm install webpack webpack-cli html-webpack-plugin

awesome-typescript-loader iso-morphic-style-loader to-string-loader postcss-loader css-loader mini-css-extract-plugin sass-loader @ngtools/webpack --save-dev


Jetzt müssen noch ein paar Dateien angelegt und geändert werden. Dafür sollte die Index.cshtml Datei im body wie folgt aussehen:


<body>

<app-root>

   ...Loading

</app-root>

  <script src="~/app/polyfills.js" asp-append-version="true"></script>

  <script src="~/app/app.js" asp-append-version="true"></script>

 

</body>

In der neu erstellten package.json-Datei können wir nun unser eigenes Webpack-Build-Script anlegen. Hierfür müssen im „scripts“ Teil folgende Zeilen hinzugefügt werden.

 

"webpack-dev.app": "set NODE_ENV=development&& webpack -d --color --display-modules",

"webpack-prod.app": "set NODE_ENV=production&& webpack -p --color --display-modules"


Nachdem die Datei gespeichert wurde tauchen im Taskrunner Explorer webpack-dev.app und webpack-prod.app als Optionen auf. Erstere wird Angular im development und letztere im production mode bauen.

Weiterhin benötigen wir eine webpack.config.js Datei in unserem Projektordner mit folgendem Inhalt:

/// <binding />

var isDevBuild = process.env.NODE_ENV !== 'production' && process.argv.indexOf('--env.prod') < 0;

var ENV = process.env.NODE_ENV = process.env.ENV = isDevBuild ? 'development' : 'production';

const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;

const path = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');

const webpack = require("webpack");

var config = {

      output: {

            path: path.resolve(__dirname, './wwwroot/app'),

            publicPath: isDevBuild ? '/app/' : 'app/',

            filename: '[name].js',

      },

      entry: {

            'app': ['./src/main.ts'],

            'polyfills': "./src/polyfills.ts",

      },

 

      resolve: {

            extensions: ['.ts', '.js']

      },

 

      module: {

            rules: [

              {

                test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,

                loader: '@ngtools/webpack'

              },

                  {

                        test: /\.ts$/,

                        loaders: [

                              {

                                   loader: 'awesome-typescript-loader',

                              }

                        ]

                  }

          ,

              {

                test: /\.html$/, loader: 'raw-loader'

              }

              , {

          test: /\.(sa|sc|c)ss$/,loader: 'raw-loader'

      }

            ]

      },

      devtool: isDevBuild ? 'cheap-module-eval-source-map' : false,

      plugins: [

            new webpack.optimize.ModuleConcatenationPlugin(),

        new MiniCssExtractPlugin({

          filename: "[name].css",

          chunkFilename: "[id].css"

        }),

            new webpack.DefinePlugin({

                  'process.env': {

                        'ENV': JSON.stringify(ENV)

                  }

            }),

            new webpack.NamedModulesPlugin(),

        new AngularCompilerPlugin({

          tsConfigPath: './tsconfig.json',

          entryModule: 'src/app/app.module#AppModule',

          sourceMap: true

        }),

      ].concat(isDevBuild ? [

      ] : [

                  // Plugins that apply in production builds only

                  new webpack.LoaderOptionsPlugin({

                        minimize: true

                  })

            ]),

}

 

module.exports = [config];


Jetzt können wir unsere App auch schon bauen. Hierfür einfach webpack-dev.app aus dem Taskrunner Explorer starten und warten, bis der Prozess abgeschlossen wurde. Anschließend kann die Website direkt getestet werden.

Mit der oben dargestellten Config wurde unsere App bereits mit dem Ahead of Time Compiler gebaut.
Wie der Titel dieses Artikels schon suggeriert, können Apps in Angular entweder Just in Time oder Ahead of Time “gebaut” werden.

Anwendungen die den Just in Time Compiler nutzen sind deutlich größer, als Ahead of Time, da hier noch viele unnötige Librarys und der Angular Compiler mitgeladen werden müssen. Weiterhin ist die Performce der App in der Regel schlechter, da Angular erst einmal bei jedem ersten Request die Quellen kompiliert.

Wird hingegen der Ahead of Time Compiler verwendet, wie in unserem Beispiel, wird die Angular-App bereits im Bauprozess kompiliert. Hierdurch wird zum einen die Angular Framework Größe, die heruntergeladen werden muss, reduziert, und die Ausführung im Browser beschleunigt. Weiterhin fallen, anders als bei JiT, Template-Fehler schon während des Bauprozesses auf, was das Debugging der App deutlich erleichtert. Weiterhin werden ungenutzte Codeteile durch Tree Shaking im Bauprozess entfernt, wodurch viele unnötige Librarys nicht mehr in der fertigen App landen. Vergleicht man die Ergebnisse von JiT und AoT lässt sich feststellen, dass diese Angular Beispielanwendung von über 713KB auf 280KB reduziert wurde.

 

 

zurück