What is the difference between Angular AOT and JIT compiler

I am immersed in angular 4 and I am trying to understand compilation. I read that AOT and JIT compile TypeScript into JavaScript regardless of whether it is server-side or client-side. If I compile it when I create it using Webpack and grab and deploy this miniature javascript, how do AOT and JIT even get into the picture?

+4
angular compilation
Aug 16 '17 at 0:37
source share
3 answers

I read that AOT and JIT compile TypeScript in JavaScript, whether server-side or client-side.

No, this is not what the AOT and JIT compilers do. TypeScript is translated into JavaScript using the TypeScript compiler.

Angular compiler

There are two compilers that do the hard work of building and generating code:

The view compiler compiles component templates and creates view factories . It parses expressions and html elements inside the template and goes through many standard compiler phases:

parse-tree (lexer) -> abstract-syntax-tree (parser) -> intermediate-code-tree -> output 

A vendor compiler compiles module suppliers and generates module factories .

JIT vs AOT

These two compilers are used in both JIT and AOT compilation. The JIT and AOT collections differ in how they obtain metadata associated with a component or module:

 // the view compiler needs this data @Component({ providers: ... template: ... }) // the provider compiler needs this data @NgModule({ providers: ... }); 

The JIT compiler uses runtime to retrieve data. The functions of the @Component and @NgModule decorator @Component @NgModule and they attach metadata to the component or module class, which is later read by Angular compilers using reflective capabiliteis (Reflect library).

The AOT compiler uses the static code analysis provided by the TypeScript compiler to extract metadata and is independent of code evaluation. Therefore, it is slightly limited compared to the JIT compiler, since it cannot evaluate explicit code - for example, it requires exporting a function:

 // this module scoped function function declarations() { return [ SomeComponent ] } // should be exported export function declarations() { return [ SomeComponent ]; } @NgModule({ declarations: declarations(), }) export class SomeModule {} 

Again, both the JIT and AOT compilers are basically wrappers for extracting metadata associated with a component or module, and both of them use a basic presentation and provider mechanism to generate plants.

If I compile it when I create it using Webpack and grunt and deploy this miniature javascript, how do AOT and JIT even get into the image?

Angular provides a webpack plugin that translates from TypeScript at build time. This plugin can also compile your AOT project so that you do not include the JIT compiler in the package and do not compile on the client.

+8
Aug 16 '17 at 7:21
source share

First of all, angular moves away from compiling JIT. I hope we see this at angular@5.xx

The angular compiler accepts all metadata that you write using decorators such as

 @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 analyzes it. He then takes a template and style sheet and parses it. The compiler goes through many steps, which I will not describe here. You can see the next page that describes the compilation process. There is also a great chat from Tobias Bosch. Finally, the compiler creates ngfactories to instantiate our application.

I think the main differences between AOT in JIT are

  • when and where angular starts compilation
  • how the collector collects metadata
  • what format ngfactory compiler give ngfactory

Jit compiler

It works on the client side in our browser every time the page loads .

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

1) direct API

for example, we can declare our component as

 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 can be written to ES5. The JIT compiler will read the static properties annotations and propMetadata . AOT compiler will not 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 above code is usually generated by some library. The angular package also has the same format. This will also not work with aot. We must send the metadata.json file with our library to compile AOT.

3) getting metadata created by calling decorators

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

Typescript compiler converts previous 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 the component decoder

 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 no longer uses the Reflect api . The compiler reads data directly from the __annotations__ property

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

JIT compiler creates javascript ngfactories

AOT compiler

runs on server side (nodejs) during build using ngc .

Using AOT does not execute the compilation stage at run time. When we launch our application in a browser, we already precompiled ngfactories . This gives us better performance at the beginning and lazy workload. Nor do we ship the @angular/compiler code in our production kit. But our package can grow significantly due to our ngfactories code.

The AOT compiler uses the Typescript api to parse typescript code. To obtain metadata, the compiler navigates through StaticSymbolResolver and the MetadataCollector APIs .

Therefore, it accepts the app.component.ts file and creates the typescript object model. Therefore, our AppComponent class will be represented as a NodeObject with type 229 ( ClassDeclaration )

enter image description here

as we can see, this object has the decorators property

enter image description here

and a special typescript wrapper written by the angular command and calling tsc-wrapper does the hard work to extract this metadata.

When the compiler encounters a d.ts file , it tries 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)]; } } 

Finally, the AOT compiler uses TypeScriptEmitter to produce typescript ngfactories (angular <4.4. 0)

see also

+7
Aug 16 '17 at 21:21
source share

After the browser loads your application packages, the Angular compiler (packaged inside vendor.bundle.js) compiles the templates from main.bundle.js. This is called Just-in-Time compilation. This term means that compilation occurs when packets arrive in the browser.

The disadvantages of compiling JIT are:

  • There is a gap between download packages and the display of the user interface. This time was spent compiling JiT. In a small application, this time is minimal, but in large applications, JiT compilation can take several seconds, so the user needs to wait longer just by seeing your application.

  • The Angular compiler should be included in the vendor.bundle.js file, which adds the size of your application.

Using JiT compilation in prod is not recommended, and we want the templates to be precompiled in JavaScript before creating the packages. This is what the Forward compilation (AoT) is.

The benefits of compiling AoT are as follows:

  • The browser can display the user interface immediately after downloading the application. No need to wait for code compilation.

  • The ngc compiler is not part of vendor.bundle.js, and as a result, your application may be smaller.

If you are using Webpack, you need to call the ngc compiler to run AoT. For example:

 "build:aot": "ngc -p tsconfig.json && webpack --config webpack.config.js" 
+4
Aug 16 '17 at 1:40 on
source share



All Articles