Upgrade to Angular 4 with AOT Compiler

@jurisicmarko

Why not Angular 3?

  • misalignment of the router package’s version:

http://angularjs.blogspot.co.at/2016/12/ok-let-me-explain-its-going-to-be.html

Angular 4.0.0

invisible makeover

  • backwards compatible with 2.x.x for most applications.

  • smaller and faster

  • improved *ngIf and *ngFor

  • updated Typescript version

  • source maps for templates
<div *ngIf="userList | async as users; else loading">
  <user-profile *ngFor="let user of users; count as count" [user]="user">
  </user-profile>
 <div>{{count}} total users</div>
</div>
<ng-template #loading>Loading...</ng-template>

New *ngIf Syntax

Improved template error messages

Upgrade

npm install 
@angular/common@latest @angular/compiler@latest 
@angular/compiler-cli@latest @angular/core@latest 
@angular/forms@latest @angular/http@latest 
@angular/platform-browser@latest 
@angular/platform-browser-dynamic@latest 
@angular/platform-server@latest 
@angular/router@latest @angular/animations@latest typescript@latest --save

Angular CLI migration

npm uninstall -g @angular/cli
npm cache clean
npm install -g @angular/cli@latest
  • Rename angular-cli.json to .angular-cli.json
  • Add environmentSource to .angular-cli.json 
  • Install new version of (global) angular-cli:
"environments": {
  "source": "environments/environment.ts",
  "dev": "environments/environment.ts",
  "prod": "environments/environment.prod.ts"
}
"environmentSource": "environments/environment.ts",
"environments": {
  "dev": "environments/environment.ts",
  "prod": "environments/environment.prod.ts"
}

before

after

$ ng build
$ rm -rf node_modules
$ npm install
$ ng build -w

Angular 4.0.0

Angular 2.4.0

Animations from core package are marked as deprecated (compiles but fails at runtime)

import { Component, OnInit, Input, ElementRef } from "@angular/core";
import { trigger, state, style, transition, animate, keyframes, group } from "@angular/animations";

Ahead-of-Time (AOT) Compiler

  • Components and templates must be converted to executable JavaScript by the Angular compiler.

  • Just-in-time in browser is the standard approach during development

  • Runtime performance penalty

  • AOT can improve performance and help catch template errors early

https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

Why AOT

  • Faster rendering
  • Fewer asynchronous requests
  • Smaller Angular framework download size
  • Detect template errors earlier
  • Better security
$ ng build --prod

Lets give it a shot

AOT not advertised stuff

  • All properties used in templates must have default visibility or be public
  • Problem with bootstrapping using promises
export function bootstrapPds(configService: ConfigService): () => Promise<BootstrapConfig> {
    return () => configService.loadWithPromise(PATH_CONFIG_BOOTSTRAP);
}

@NgModule({
    imports: [ CommonModule ]
})
export class CoreModule {

    constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
        if(parentModule) {
            throw new Error(`CoreModule is already loaded. Import in the AppModule only`);
        }
    }

    static forRoot(preferenceServiceConfig: PreferenceServiceConfig): ModuleWithProviders {
        return {
            ngModule: CoreModule,
            providers: [
                ApiGatewayService,
                AuthGuard,                
                DepsRdepsService,
                {
                    provide: PreferenceServiceConfig,
                    useValue: preferenceServiceConfig
                },
                {
                    provide: APP_INITIALIZER,
                    useFactory: bootstrapPds,
                    deps: [ ConfigService, Http ],
                    multi: true
                },
                SnapshotService,
                ValidationService
            ]
        }
    }

}

Performance comparison

2.4.0

4.0.0

Bundle comparison

Development build

Production build

webpack-bundle-analyser

  • analyze bundle content
  • works even with minified bundles
  • needs webpack stats as input 

webpack-bundle-analyser and angular-cli

  • from 4.0 use --stats-json flag 
  • for older versions patch webpack-config.js to use webpack-stats plugin:
var StatsWriterPlugin = require("webpack-stats-plugin").StatsWriterPlugin;

// ...
 getTargetConfig(webpackConfigOptions) {
        var statWriter = new StatsWriterPlugin({
            chunkModules: true,
            fields: null,
            filename: "stats.json" // Default
        });
        switch (webpackConfigOptions.buildOptions.target) {
            case 'development':
                var data  =  webpack_configs_1.getDevConfig(webpackConfigOptions);
                if(typeof(data.plugins) === 'undefined') {
                    data['plugins'] = [];
                }
                data.plugins.push(statWriter);
                return data ;
// ...
node ./node_modules/webpack-bundle-analyzer/src/bin/analyzer ./dist/stats.json

webpack-bundle-analyser 

2.4 Development bundle

4.0 Development bundle

4.0 Production bundle

Conclusion

  • Painless upgrade
  • Great performance improvements
  • AOT compiler effort pays off

Questions?

Resources

Upgrade to Angular 4 with AOT Compiler

By Marko Jurišić

Upgrade to Angular 4 with AOT Compiler

  • 1,682