Demystifying

Ahead-Of-Time Compilation

In Angular

Let me tell ya a

Story...

Wassim Chegham

Dev Advocate

@manekinekko

let's talk about

Compilers

DUDE...

SERIOUSLY

What is a Compiler?

A compiler is a computer program that transforms source code written in a programming language into another computer language [...] The most common reason for converting source code is to create an executable program.

I mean...

Angular

Template

Compiler

Template Strings

{Parser, Lexer, Tokenizer...}

VM CODE

running application

Compiler

2 Traditional Compilations

〈JIT, AOT〉

What is JIT?

Just-in-time (JIT) compilation, also known as dynamic translation, is compilation done during execution of a program – at run time...

Components

B

U

I

L

D

B

R

O

W

S

E

R

Code Gen

JIT Compilation

VM Code

JIT

 

Dynamic Compilation

OR

JIT drawbacks...

Bundle Size
Performance
Bootstrapping Security

May Be

Can Help

Ahead Of Time

What is AOT?

Ahead-of-time (AOT) compilation is the act of compiling a high-level programming language, into a native machine code with the intention of executing the resulting binary file natively. AOT produces machine optimized code...

Components

B

U

I

L

D

B

R

O

W

S

E

R

Code Gen

AOT Compilation

VM Code

AOT

 

Static Compilation

OR

AOT Needs

Application

Context

However...

In Angular...

@NgModule()

Is The Context

Angular modules

@NgModule({
  imports: [
    BrowserModule, MdModule,
    HttpModule, RoutesModule...
  ],
  declarations: [
    HomeComponent, PersonComponent...
  ],
  providers: [ AwesomeService ],
  bootstrap: [ AppComponent ]
})

Angular in JIT mode

// The browser platform with a compiler
import { 
   platformBrowserDynamic 
} from '@angular/platform-browser-dynamic';


// The app module
import { AppModule } from './app.module';


// Compile (JIT) and launch the module
platformBrowserDynamic().bootstrapModule(
   AppModule
);

Angular in AOT mode

// The browser platform with a compiler
import { 
   platformBrowser 
} from '@angular/platform-browser';

// The generated app factory (AOT)
import { 
   AppModuleNgFactory
} from './app.module.ngfactory';

// Launch with the app module factory.
platformBrowser().bootstrapModuleFactory(
   AppModuleNgFactory
);

Angular in AOT mode

$ npm install \
        @angular/compiler-cli \
        @angular/platform-server \
        @angular/compiler \
        typescript@next --save

$ ./node_modules/.bin/ngc -p tsconfig.aot.json

$ # generates app.module.ngfactory.ts
$ # generates app.component.ngfactory.ts
$ # generates app.component.css.shim.ts
$ # generates ...

Angular Code Gen

(example of app.component.ngfactory.ts)

Oh! Also

Tree—Shaking*

*which is not Dead Code Elimination, BTW

Good News...

~30-60%

Less Code*...

*may not be relevant to huge apps due to the codegen process

No More Dynamic Template Compilation

Less

Security

Risks

No more evals

Faster

Time

To Interaction

Using the cli...

const { AotPlugin } = require('@ngtools/webpack');
const tsconfig = root('./src/tsconfig.browser.json');

module.exports = {
    //...
    plugins: [
        new AotPlugin({
            tsConfigPath: tsconfig
        })
    ]
}

Using webpack...

Bonus...

Make your code

Statically Analyzable...

Lambda expression

// bad
providers: [{
  provide: UrlSerializer,
  useFactory: (xDebugService) => {
    return new XUrlSerializer(xDebugService)
  },
  deps: [XDebugService]
}, ...]

Error encountered resolving symbol values statically.
Calling function 'XXXXX', function calls are not supported.
Consider replacing the function or lambda with a reference
to an exported function...

Lambda expression

// good
export function setupUrlSerializer(xDebugService) {
  return new XUrlSerializer(xDebugService);
}

providers: [{
  provide: UrlSerializer,
  useFactory: setupUrlSerializer,
  deps: [XDebugService]
}, ...]

Error encountered resolving symbol values statically.
Calling function 'XXXXX', function calls are not supported.
Consider replacing the function or lambda with a reference
to an exported function...

Access modifiers

// bad
@Component({template: `{{ foo }}`})
export class AppComponent {
  private foo: any;
}

// good
@Component({template: `{{ foo }}`})
export class AppComponent {
  public foo: any;
}

Error at /app.component.ngfactory.ts Property 'foobar' is private and only accessible within class 'AppComponent'.

Named exports

// bad
@Component({})
class AppComponent {}
export default AppComponent;

// good
@Component({})
export class AppComponent {}

can't find symbol undefined exported from module app.component.ts

Know/found others?

tweet them to me

@manekinekko

Thanks for listening...

manekinekko

Resources

Demystifying AOT compilation in Angular

By Wassim Chegham

Demystifying AOT compilation in Angular

The introduction of NgModule was a huge news for the Angular community. This new API is supposed to help the AOT compilation by providing the compilation context and generate a much lighter application bundle. Let's see how does AOT work...

  • 15,142

More from Wassim Chegham