Angualr中的AOT(Ahead-of-Time Compilation)编译(一)

翻译 2017年01月06日 21:37:43

--------------------------------------------------------------------------------------------------------------------------------------------

最近学习Angular2的内容,国内资料较少,发现一篇对于AOT讲的特别好文章,以备自己学习回顾。

尝试翻译如下。如有任何版权相关问题,请联系。如有翻译错误或不准确的地方欢迎大家留言,我会积极修正。

非专业,不喜勿喷。

作者:Minko Gechev

原文链接:http://blog.mgechev.com/2016/08/14/ahead-of-time-compilation-angular-offline-precompilation/

--------------------------------------------------------------------------------------------------------------------------------------------

Angualr中的AOT(Ahead-of-Time Compilation)编译

作者写这篇文章的目的是因为该大牛为angular-seed (
关于angular-seed有仁兄已经写了博客,http://blog.csdn.net/ybdesire/article/details/50551486)框架添加了AOT,
导致有很多人提出了各种问题,然后作者详细解释了一下AOT的原理和用途。
主要有如下topic:
  • Angular中为什么需要编译?
  • 什么内容需要编译?
  • 如何进行编译?
  • 编译在什么时间点发生? Just-in-Time (JiT) vs Ahead-of-Time (AoT).
  • AOT有哪些优势?使用AOT我们能得到什么?
  • AOT编译是如何工作的,工作原理是什么?
  • 相对于JIT,使用AOT我们失去了哪些特性?

Angualr中为什么需要编译

简单来说:我们需要编译来达到更高效率的Angular程序。对于效率主要是指性能的改善,
但有时也带来带宽等方面的消耗。
AngularJS 1.x有渲染和变化检测的动态实现。例如,在AngularJS 1.x中的编译器是通用编译器。
它被设计用来执行任何模板的动态计算工作。虽然大多数情况下,它工作的特别好。因为动态特性,
导致JavaScript虚拟机(VM)只能进行较低层次的优化计算
由于VM不知道对象的结构,提供脏检查逻辑(即scope)的上下文,它的内联高速缓存得到了大量
的失误,从而减慢执行速度。

Angualr2和以上版本,使用了不同的实现方式,不再为每一个单独的组件使用相同的逻辑执行渲染和变化检测,
该框架runtime或build生成VM友好或者说VM更加容易识别和优化的代码。这使得JavaScript虚拟机
能够更加快速的访问缓存和执行变化检测/渲染。

请看如下例子:
// ...
Scope.prototype.$digest = function () {
  'use strict';
  var dirty, watcher, current, i;
  do {
    dirty = false;
    for (i = 0; i < this.$$watchers.length; i += 1) {
      watcher = this.$$watchers[i];
      current = this.$eval(watcher.exp);
      if (!Utils.equals(watcher.last, current)) {
        watcher.last = Utils.clone(current);
        dirty = true;
        watcher.fn(current);
      }
    }
  } while (dirty);
  for (i = 0; i < this.$$children.length; i += 1) {
    this.$$children[i].$digest();
  }
};
// ...
上面代码来源于Angualr1.x的实现,上面我们在整个作用域树上进行深度优先搜索,寻找绑定的变化.。
这种方法将适用于任何指令。然而,与指令特定的代码相比,它明显运行速度较慢。
// ...
var currVal_6 = this.context.newName;
if (import4.checkBinding(throwOnChange, this._expr_6, currVal_6)) {
    this._NgModel_5_5.model = currVal_6;
    if ((changes === null)) {
        (changes = {});
    }
    changes['model'] = new import7.SimpleChange(this._expr_6, currVal_6);
    this._expr_6 = currVal_6;
}
this.detectContentChildrenChanges(throwOnChange);
// ...
上面这段代码来自于Angualr-seed项目,用来实现生成detectChangesInternal的方法。它使用直接属性访问
获取单个绑定的值,并使用最有效的方法将它们与新值进行比较。一旦发现它们的值是不同的,它只更新
DOM元素的影响。

通过回答”为什么需要编译?“我们同时回答了“什么内容需要编译”。我们希望编译组件的模板(templates)
成为JavaScript的classes。这些类(classes)提供在绑定过程中检测变化的方法和渲染用户接口的方法。
通过这种方法,我们就不需要同底层平台存在联系(除了markup格式)。换句话说,通过实现不同的
渲染器(renderer),我们能够不需要任何代码修改使用同样AOT编译后的模块进行渲染。
这样的模块(component)能够被NativeScript渲染。例如:渲染器能够尽可能的理解传递的参数。

Just-in-Time (JiT) vs Ahead-of-Time (AoT)

这一节同时包含编译在什么时间点发生?”的答案。
Anuglar的编译器比较cool的是可以在runtime(如用户的browser中)引入也可以build时点
(作为build流程的一部分)引入。
由于Angualr的便携性,我们可以在任何Javascript VM上运行我们的framework。那么我们
为什么不让Angular的编译器同时运行在browser和node上呢?

JIT编译中的事件流(event flow)

没有AOT时我们典型的开发流程:
  • 使用TypeScript开发Angular应用
  • 使用Tsc编译我们的应用
  • 打包(Bundling
  • 压缩最小化(Minification
  • 发布(Deployment
当用户打开浏览器查看我们已经部署的应用时,他将经历如下步骤(不包含内容安全策略(CSP)):
  • 下载JavaScript资源(assets)
  • Angular渲染页面(Angular bootstraps
  • Augular进行JIT编译过程,生成我们每个模块的JavaScript。
  • 应用被渲染(rendered)完成,展示给用户

AOT编译中的事件流(event flow)

使用AOT,经历如下步骤:

  • 使用TypeScript开发Angular应用
  • 使用ngc编译我们的应用.
    • 使用Angular编译器将模板(templates)编译成通常的TypeScript。
    • 将TypeScript编译JavaScript.
  • 打包(Bundling
  • 压缩最小化(Minification
  • 发布(Deployment

尽快看起来我们有更多的编译过程,但是对于用户来说,他只需要经历如下步骤:

  • 下载JavaScript资源(assets)
  • Angular渲染页面(Angular bootstraps
  • 应用被渲染(rendered)完成,展示给用户

我们可以看到对于用户来说,AOT编译使得第三部消失了。这就意味着更好更快的用户体验(UX)。
并且我们已经有软件支持自动编译了。NB如angular-seedangular-cli

综上所述,我们可以看出Angualr中JIT同AOT编译的主要不同点:

  • 编译选择的位置不同

  • JIT生成JavaScript(TypeScript没太关注这部分因为代码需要在浏览器被编译为JavaScript)。
    AoT生成TypeScript.

下一遍将更加深入的分析AOT,敬请期待。




Java编译(一) Java三种编译方式:前端编译 JIT编译 AOT编译

Java编译涉及到非常多的知识层面:编译原理、语言规范、虚拟机规范、本地机器码优化等;下面我们先来看下Java体系中的三种编译方式:前端编译、即时编译(JIT编译)、静态提前编译(AOT编译)解它们各...
  • tjiyu
  • tjiyu
  • 2016年12月19日 21:24
  • 5061

AOT和JIT

一个程序的编译过程可以是步骤迭代式的,即每一轮步骤结束后得到的结果都可独立运行,比如,先构造AST再输出字节码,中间状态AST也是可以解释执行的。由于编译的本质就是代码转换,因此对一个语言可以有多个独...
  • xtlisk
  • xtlisk
  • 2014年09月06日 10:17
  • 3400

JIT(动态编译)和AOT(静态编译)编译技术比较

Java 应用程序的性能经常成为开发社区中的讨论热点。因为该语言的设计初衷是使用解释的方式支持应用程序的可移植性目标,早期 Java 运行时所提供的性能级别远低于 C 和 C++ 之类的编译语言。尽管...
  • Hsuxu
  • Hsuxu
  • 2013年07月13日 20:51
  • 22481

Angular2 AoT编译以及Rollup摇树优化

1.先使用Angular-cli生成一个新的项目 ng new angular2-aot-rollup-seed2.创建完成之后,会自动生成一个根模块AppModule,为了说明问题,使用 ng g ...
  • zsz459520690
  • zsz459520690
  • 2017年01月12日 11:28
  • 5812

Angular2之aot编译及Rollup优化

最近开发的一款移动应用用了Angular2框架,直接ng build的话动不动程序就要好几M,于是采取Angular2的aot编译及Rollup优化压缩程序。过程遇坑无数,说多了都是泪,现在问题解决了...
  • jyliyue
  • jyliyue
  • 2017年09月13日 09:49
  • 273

AOT/JNI/Vala 的比较

转自:http://en.wikipedia.org/wiki/AOT_compiler An ahead-of-time (AOT) compiler is a compiler that ...
  • yasi_xi
  • yasi_xi
  • 2013年08月11日 12:01
  • 2394

Unity3D游戏在iOS上因为trampolines闪退的原因与解决办法

原文 http://7dot9.com/?p=444 崩溃的情况 进入游戏一会儿,神马都不要做,双手离开手机,盯着屏幕看吧,游戏会定时从服务器那儿读取一些数据,时间一长,闪退了...
  • cyxisgreat
  • cyxisgreat
  • 2015年04月13日 21:54
  • 1618

关于angular4编译生产模式ng build --prod --aot的报错

项目package.json 的angular/cli版本为1.3.2,使用cnpm安装依赖包,用ng build --prod --aot编译的时候会报如下错: 解决方法: ...
  • yxmanyxman
  • yxmanyxman
  • 2017年12月15日 15:49
  • 412

angular4开发环境搭建以及项目启动过程

1.安装Node.js®和npm,node官网下载安装即可 2.请先在终端/控制台窗口中运行命令 node -v 和 npm -v, 来验证一下你正在运行 node 6.9.x 和 np...
  • qq_34645412
  • qq_34645412
  • 2017年08月13日 15:46
  • 3294

NG2.4.10升级NG4正式版[正式项目]:修正AOT打包报错的一些问题

前言上周五,ng4正式发布了。。很多小伙伴迫不及待的把项目升级了。。。 然后到群里各种吼,无损升级,没有什么奇葩问题,大家放心升级。。 我信了。。。把公司的项目给升级了,然后就开始掉坑了...
  • bomess
  • bomess
  • 2017年03月27日 11:44
  • 2212
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Angualr中的AOT(Ahead-of-Time Compilation)编译(一)
举报原因:
原因补充:

(最多只允许输入30个字)