The Angular Compiler 4.0 - TOBIAS BOSCH

By: ng-conf

72   0   4938

Uploaded on 04/06/2017

www.ng-conf.org

ng-conf is a two day, single track conference focused on delivering the highest quality training in the Angular JavaScript framework. 500 to 700 Developers from across the country will converge on beautiful Salt Lake City, UT to participate in training sessions by the Google Angular team, and other Angular experts. In addition to the invaluable training, ng-conf will deliver a premier conference experience for attendees, providing opportunities to network with other developers, relax at social events, and engage in some of the unique entertainment opportunities available in Utah.

Comments (6):

By anonymous    2017-09-20

At the moment ngc doesn't support watch mode. It's addition identified by the Tobias Bosch as priority features. Here is the video where he talks about that.

Original Thread

By anonymous    2017-09-20

First of all angular is moving away from JIT compilation. I hope we will see it in angular@5.x.x

Angular compiler takes all metadata you write by using decorators like

@Component({
  selector: 'my-app',
  template: '<h1>Hello</h1>'m
  styles: [ ':host { display: block }' ]
})

constructor(
  @Host() @Optional() private parent: Parent,
  @Attribute('name') name: string) {} 

@ViewChild('ref') ref;

@ContentChildren(MyDir) children: QueryList<MyDir>;  

@HostBinding('title') title;

@HostListener('click') onClick() { ... }

// and so on

and analizes it. Then it takes template and stylesheets and parses it. Compiler goes through many steps that i won't describe here. You can take a look at the following page that describes the compilation process. There is also great talk from Tobias Bosch. Finally compiler creates ngfactories to instantiate our application.

I think main differences between AOT in JIT are

  • when and where angular runs compilation
  • how compiler collects metadata
  • what's the format of ngfactory that compiler produces

JIT compiler

runs on client side in our browser on every page load.

It collects metadata by using ReflectionCapabilities API from @angular/core package. We have the following options to work with metadata in JIT mode:

1) direct API

for example we can declare our component like

export class AppComponent {
  static annotations = [
    new Component({
      selector: 'my-app',
      templateUrl: `./app.component.html`,
      styles: [ ':host { display: block }' ]
    })
  ];

  test: string;

  static propMetadata = {
      test: [new HostBinding('title')]
  };


  ngOnInit() {
    this.test = 'Some title'
  }
}

Similar code we can write in ES5. JIT compiler will read annotations and propMetadata static properties. AOT compiler won't work with it.

2) tsickle API

export class AppComponent {
  static decorators = [{
      type: Component,
      args: [{
        selector: 'my-app',
        templateUrl: `./app.component.html`,
        styles: [ ':host { display: block }' ]
      },]
  }];

  test: string;

  static propDecorators = {
    'test': [{ type: HostBinding, args: ['title'] }]
  };

  ngOnInit() {
    this.test = 'Some title'
  }
}

The code above usually is generated by some library. Angular package also has the same format. This also won't work with aot. We have to ship metadata.json file with our library for AOT compilation.

3) getting metadata created by invoking the decorators

@Component({
  selector: 'my-app',
  templateUrl: `./app.component.html`
})
export class AppComponent {
  @HostBinding('title') test = 'Some title';
}

Typescript compiler transforms the preceding code to

 var AppComponent = (function () {
    function AppComponent() {
        this.test = 'Some title';
    }
    return AppComponent;
}());
__decorate([
    HostBinding('title')
], AppComponent.prototype, "test", void 0);
AppComponent = __decorate([
    Component({
        selector: 'my-app',
        templateUrl: "./app.component.html"
    })
], AppComponent);

this code is executed in JIT mode so angular calls Component decorator

const TypeDecorator: TypeDecorator = <TypeDecorator>function TypeDecorator(cls: Type<any>) {
      // Use of Object.defineProperty is important since it creates non-enumerable property which
      // prevents the property is copied during subclassing.
      const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
          (cls as any)[ANNOTATIONS] :
          Object.defineProperty(cls, ANNOTATIONS, {value: []})[ANNOTATIONS];
      annotations.push(annotationInstance);
      return cls;
};

Today it doesn't use Reflect api anymore. Compiler reads data directly from __annotations__ property

if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
  return (typeOrFunc as any)[ANNOTATIONS];
}

JIT compiler produces javascript ngfactories

AOT compiler

runs on server side (nodejs) at build time by using ngc.

With AOT, there is no runtime compile step. When we run our application in browser we have already precompiled ngfactories. It gives us better performance at first and lazy load. We also don't ship @angular/compiler code in our production bundle anymore. But our bundle can grow significantly because of our ngfactories code.

AOT compiler uses typescript api to analize typescript code. To get metadata compiler goes through StaticSymbolResolver and MetadataCollector APIs.

So it takes app.component.ts file and creates typescript object model. So our AppComponent class will be presented like NodeObject with type 229 (ClassDeclaration)

enter image description here

as we can see this object has decorators property

enter image description here

and special typescript wrapper written by angular team and called tsc-wrapper does hard work to extract this metadata.

When compiler meets d.ts file it is trying to get metadata from metadata.json:

if (DTS.test(filePath)) {
  var metadataPath = filePath.replace(DTS, '.metadata.json');
  if (this.context.fileExists(metadataPath)) {
    return this.readMetadata(metadataPath, filePath);
  }
  else {
    // If there is a .d.ts file but no metadata file we need to produce a
    // v3 metadata from the .d.ts file as v3 includes the exports we need
    // to resolve symbols.
    return [this.upgradeVersion1Metadata({ '__symbolic': 'module', 'version': 1, 'metadata': {} }, filePath)];
  }
}

And finally AOT compiler uses TypeScriptEmitter to produce typescript ngfactories

See also

Original Thread

By anonymous    2018-01-29

I was watching The Angular Compiler 4.0 - TOBIAS BOSCH and suddenly at 1:30 of the video it was said that AST is transformed into typescript code if we use AOT compilation or javascript code if we use JIT compilation.Compilation process a snapshot of the video. now I am super confused what actually is happening under the hood? Whether (.ts) is transpiled to js first by typescript compiler and then angular compiler comes into the play or angular compiler do the job and typescript compiler comes into the play? I went through this What does the angular compiler “compile”? but apparently my doubt is not clear yet? Can anyone help me out on this?

Original Thread

Popular Videos 90

Submit Your Video

If you have some great dev videos to share, please fill out this form.