我正在潜入角度4,我试图理解编译。 我已经读过AOT和JIT都将TypeScript编译为JavaScript,无论是服务器端还是客户端。 如果我在使用Webpack和grunt构建它时编译它并部署那个缩小的javascript,AOT和JIT是如何进入图片的?

#1楼 票数:23 已采纳

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

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

角度编译器

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

视图编译器编译组件模板并生成视图工厂 它解析模板中的表达式和html元素,并经历了许多标准编译器阶段:

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

提供程序编译器编译模块提供程序并生成模块工厂

JIT vs AOT

这两个编译器用于JIT和AOT编译。 JIT和AOT编译在获取与组件或模块关联的元数据方面有所不同:

// the view compiler needs this data

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

// the provider compiler needs this data

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

JIT编译器使用运行时来获取数据。 执行装饰器函数@Component@NgModule它们将元数据附加到组件或模块类,稍后由Angular编译器使用反射capabiliteis(Reflect库)读取。

AOT编译器使用typescript编译器提供的静态代码分析来提取元数据,而不依赖于代码评估。 因此,与JIT编译器相比,它有点受限,因为它无法评估显式内代码 - 例如,它需要导出函数:

// 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和grunt构建它时编译它并部署那个缩小的javascript,AOT和JIT是如何进入图片的?

Angular提供了webpack插件 ,可以在构建期间从typescript执行转换。 这个插件也可以AOT编译你的项目,这样你就不会将JIT编译器包含在bundle中,也不会在客户端上执行编译。

#2楼 票数:18

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

Angular编译器通过使用装饰器来获取您编写的所有元数据

@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

并分析它。 然后它需要模板和样式表并解析它。 编译器经历了许多我不会在这里描述的步骤。 您可以查看描述编译过程的以下页面 Tobias Bosch也有很多话题 最后编译器创建ngfactories来实例化我们的应用程序。

我认为AIT在JIT中的主要区别在于

  • 何时何地角运行编译
  • 编译器如何收集元数据
  • 编译器生成的ngfactory的格式是什么

JIT编译器

在每个页面加载时在我们的浏览器中在客户端运行

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

1)直接API

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

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中编写类似的代码。 JIT编译器将读取annotationspropMetadata静态属性。 AOT编译器无法使用它。

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'
  }
}

上面的代码通常由某些库生成。 Angular包也具有相同的格式。 这也不适用于aot。 我们必须使用我们的库来发送metadata.json文件以进行AOT编译。

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

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

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

 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);

此代码在JIT模式下执行,因此angular 调用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;
};

今天它不再使用Reflect api了 编译器直接从__annotations__属性读取数据

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

JIT编译器生成javascript ngfactories

AOT编译器

在构建时使用ngc在服务器端(nodejs)上运行

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

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

因此它需要app.component.ts文件并创建app.component.ts对象模型。 因此,我们的AppComponent类将呈现像NodeObject229ClassDeclaration

在此输入图像描述

我们可以看到这个对象有decorators属性

在此输入图像描述

由angular团队编写并称为tsc-wrapper特殊打字稿包装tsc-wrapper 很难提取这些元数据。

当编译器遇到d.ts文件时,它试图从metadata.json获取元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)];
  }
}

最后,AOT编译器使用TypeScriptEmitter 生成打字稿ngfactories (angular <4.4.0)

也可以看看

#3楼 票数:4

浏览器加载应用程序包后,Angular编译器(在vendor.bundle.js中打包)执行main.bundle.js模板的编译。 这称为即时编译。 这个术语意味着编译发生在捆绑包到达浏览器的时间。

JIT编译的缺点是:

  1. 加载包和呈现UI之间存在时间差。 这段时间用于JiT编译。 在一个小应用程序上这次是最小的,但在较大的应用程序中,JiT编译可能需要几秒钟,因此用户需要等待更长时间才能看到您的应用程序。

  2. Angular编译器必须包含在vendor.bundle.js中,这会增加应用程序的大小。

不鼓励在prod中使用JiT编译,我们希望在创建bundle之前将模板预编译为JavaScript。 这就是Ahead-of-Time(AoT)编译的内容。

AoT编译的优点是:

  1. 浏览器可以在加载应用程序后立即呈现UI。 无需等待代码编译。

  2. ngc编译器不包含在vendor.bundle.js中,并且应用程序的结果大小可能更小。

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

"build:aot": "ngc -p tsconfig.json && webpack --config webpack.config.js"

  ask by CW1 translate from so

未解决问题?本站智能推荐:

8回复

Angular中的即时(JiT)与提前(AoT)编译

我指的是这个文档并遇到了编译概念。 可以使用 JIT 或 AOT 编译。 但是,我发现它很简短,需要详细了解以下几点, 这两种技术的区别 关于何时使用什么的建议
1回复

Angular2AoT编译器:没有错误,但是肯定有问题

我已经为此花了三天时间,试图让我的Angular 2 rc.6应用程序提前编译。 使用即时编译,应用程序可以编译并运行良好。 我已经安装了所有依赖项,运行ngc (编译器),将main.ts更改为使用platformBrowser() ,然后再次运行ngc 。 控制台中没有错误。
2回复

Angular2Ahead-of-Time编译器是否支持SASS样式表?

我想再次尝试使用Angular 2 Ahead-of-Time编译。 这将需要我的重大重构,因为我当前的设置使用需要更改的自定义构建过程。 在开始之前,我需要知道:如果我链接到styleUrls元数据中的外部.scss文件,AoT编译器是否可以工作? 或者我应该首先将我的所有样式转换
1回复

AOT编译后的angular4供应商和主要.js文件大小

MAin.bundle和vendor.bundle的大小非常大, 如何减小文件大小,因为这会导致应用程序加载缓慢
1回复

AOT编译错误:未捕获的ReferenceError:未定义require

我正在尝试使用aot编译,但是当编译完成时,控制台会打印出来 我似乎无法找到解决此问题的正确解决方案。 这是我的rollup-config.js文件 这是我的main.aot.ts文件 这是我的build.js文件!function(){“use strict”; require
3回复

Angular2编译用于生产

如何编译Angualar2并进行生产部署? 我检查了很多类似网站这 (但是这给错误和bundle.min.js不能从可用index.html -也许我是错的)。 也尝试了angular-cli,但是对于RC-4再次不起作用。 想知道什么是最佳实践,因为tsc已经创建了js,是否应该将它们
1回复

angular2中的递归动态模板编译

我的一些工作基于此处描述的相同问题: 使用 Angular 2.0 编译动态组件的动态模板 如何使用/创建动态模板来使用 Angular 2.0 编译动态组件? 可以在此处找到上述问题中描述的工作 plunker。 如果动态详细信息尝试创建另一个在模板中使用动态详细信息的动态视图,则会出现问题。 如
1回复

从Angular2/Ionic2中的编译中禁用部分标记

有没有办法在Angular2编译期间忽略部分标记? 问题是我有一个使用jQuery和<template>标记的附加库,并且由于Angular,当库尝试使用$('template')选择器到达DOM时, <template> html标记不存在于DOM中。