首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Angular AOT和JIT编译器的区别是什么

Angular AOT和JIT编译器的区别是什么
EN

Stack Overflow用户
提问于 2017-08-16 08:37:36
回答 3查看 12.7K关注 0票数 14

我正在深入研究angular 4,并试图理解编译过程。我读到过AOT和JIT都将TypeScript编译为JavaScript,无论是在服务器端还是在客户端。如果我编译它,当我和Webpack一起构建它的时候,嘟嘟声和部署那个缩小的javascript时,AOT和JIT是如何出现在画面中的?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-08-16 15:21:03

我读到过AOT和JIT都将TypeScript编译成JavaScript,无论是在服务器端还是在客户端。

不,这不是AOT和JIT编译器所做的。使用TypeScript编译器将typescript转换为JavaScript。

Angular编译程序

有两个编译器可以完成编译和代码生成的繁重工作:

视图编译器编译组件模板和generates view factories。它解析模板中的表达式和html元素,并经历许多标准编译器阶段:

代码语言:javascript
复制
parse-tree (lexer) -> abstract-syntax-tree (parser) -> intermediate-code-tree -> output

提供程序编译器编译模块提供程序和generates module factories

JIT与AOT

这两个编译器同时用于JIT和AOT编译。JIT和AOT编译的不同之处在于它们如何获取与组件或模块相关联的元数据:

代码语言:javascript
复制
// the view compiler needs this data

@Component({
   providers: ...
   template: ...
})

// the provider compiler needs this data

@NgModule({
   providers: ...
});

JIT编译器使用运行时来获取数据。装饰器函数@Component@NgModule被执行并映射到组件或模块类,稍后由Angular编译器使用反射功能( they attach metadata库)读取。

AOT编译器使用typescript编译器提供的静态代码分析来提取元数据,并且不依赖于代码评估。因此,与JIT编译器相比,它有一点局限性,因为它不能计算显式代码-例如,它需要导出一个函数:

代码语言:javascript
复制
// this module scoped function

function declarations() {
  return [
    SomeComponent
  ]
}

// should be exported

export function declarations() {
  return [
    SomeComponent
  ];
}
@NgModule({
  declarations: declarations(),
})
export class SomeModule {}

同样,JIT和AOT编译器主要是用于提取与组件或模块相关联的元数据的包装器,它们都使用底层视图和提供程序编译器来生成工厂。

如果我正在编译它,当我和Webpack一起构建它的时候,

和JIT是如何出现在画面中的呢?

Angular提供了在构建过程中执行从typescript转换的webpack plugin。这个插件还可以AOT编译你的项目,这样你就不会把JIT编译器包含在包中,也不会在客户机上执行编译。

票数 23
EN

Stack Overflow用户

发布于 2017-08-17 05:21:22

首先,angular正在远离JIT编译。我希望我们能在angular@5.x.x中看到它

Angular编译器接受您通过使用装饰器编写的所有元数据,例如

代码语言:javascript
复制
@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

并进行分析。然后它获取模板和样式表并对其进行解析。编译器经历了许多步骤,我在这里不再赘述。您可以查看描述编译过程的the following page。还有来自Tobias Bosch的great talk。最后,编译器创建新工厂来实例化我们的应用程序。

我认为AOT在JIT中的主要区别是

angular何时何地运行compilation

  • how编译器
  • 采集编译器生成的ngfactory的格式

JIT编译器

在我们的浏览器中,每次加载页面时,都会在客户端运行。

它通过使用@angular/core包中的ReflectionCapabilities API来收集元数据。我们有以下选项可以在JIT模式下使用元数据:

1)直接接口

例如,我们可以像这样声明我们的组件

代码语言:javascript
复制
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'
  }
}

我们可以用ES5编写类似的代码。即时编译器将读取annotationspropMetadata静态属性。AOT编译器不能与它一起工作。

2) tsickle

代码语言:javascript
复制
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'
  }
}

上面的代码通常是由某个库生成的。Angular包也有相同的格式。这也不适用于aot。我们必须将metadata.json文件与我们的库一起提供,以便进行AOT编译。

3)获取通过调用装饰器创建的元数据

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

Typescript编译器将前面的代码转换为

代码语言:javascript
复制
 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);

此代码是在即时模式下执行的,因此angular calls Component decorator

代码语言:javascript
复制
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;
};

今天是it doesn't use Reflect api anymore。编译器直接从__annotations__属性读取数据

代码语言:javascript
复制
if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
  return (typeOrFunc as any)[ANNOTATIONS];
}

JIT编译器生成javascript JIT工厂

AOT编译器

通过使用ngc. ngc.,在构建时运行在服务器端(nodejs)

使用AOT,没有运行时编译步骤。当我们在浏览器中运行我们的应用程序时,我们已经预编译了ngfactories。它给我们带来了更好的性能和延迟加载。我们也不再在生产捆绑包中发布@angular/compiler代码。但是由于我们的ngfactories代码,我们的捆绑包可以显着增长。

AOT编译器使用typescript api来分析typescript代码。要获取元数据编译器,需要通过StaticSymbolResolverMetadataCollector API。

因此,它获取app.component.ts文件并创建typescript对象模型。因此,我们的AppComponent类将像NodeObject一样使用类型229 (ClassDeclaration)表示

正如我们所看到的,这个对象具有decorators属性

和特殊的typescript包装器,由angular团队编写并调用tsc-wrapper does hard work来提取元数据。

当编译器执行meets d.ts file时,它会尝试从metadata.json获取元数据

代码语言:javascript
复制
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)];
  }
}

最后利用TypeScriptEmitter生成typescript ngfactories (angular < 4.4.0)

另请参阅

票数 18
EN

Stack Overflow用户

发布于 2017-08-16 09:40:37

在浏览器加载应用程序包之后,Angular编译器(打包在vendor.bundle.js中)执行来自main.bundle.js的模板编译。这就是所谓的即时编译。这个术语意味着编译是在包到达浏览器时发生的。

JIT编译的缺点是:

  1. 在加载包和渲染UI之间有一段时间间隔。这段时间花在JiT编译上。在小型应用程序中,这种时间很短,但在大型应用程序中,JiT编译可能需要几秒钟的时间,因此用户需要等待更长时间才能看到您的应用程序。
  2. Angular编译器必须包含在vendor.bundle.js中,这会增加应用程序的大小。

不鼓励在prod中使用JiT编译,我们希望在创建包之前将模板预编译到JavaScript中。这就是提前(AoT)编译的意义所在。

AoT编译的优点是:

  1. 一旦你的应用被加载,浏览器就可以渲染UI。没有必要等待代码compilation.
  2. The ngc编译器没有包含在vendor.bundle.js中,并且您的应用程序的结果可能会更小。

如果你使用的是Webpack,要做AoT你需要调用ngc编译器。例如:

代码语言:javascript
复制
"build:aot": "ngc -p tsconfig.json && webpack --config webpack.config.js"
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45703443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档