CW1*_*CW1 13 compilation angular
我正在潜入角度4,我试图理解编译.我已经读过AOT和JIT都将TypeScript编译为JavaScript,无论是服务器端还是客户端.如果我在使用Webpack和grunt构建它时编译它并部署那个缩小的javascript,AOT和JIT是如何进入图片的?
Max*_*kyi 23
我已经读过AOT和JIT都将TypeScript编译为JavaScript,无论是服务器端还是客户端.
不,这不是AOT和JIT编译器所做的.使用typescript编译器将TypeScript转换为JavaScript.
有两个编译器可以完成编译和代码生成的艰苦工作:
视图编译器编译组件模板并生成视图工厂.它解析模板中的表达式和html元素,并经历了许多标准编译器阶段:
parse-tree (lexer) -> abstract-syntax-tree (parser) -> intermediate-code-tree -> output
Run Code Online (Sandbox Code Playgroud)
提供程序编译器编译模块提供程序并生成模块工厂.
这两个编译器用于JIT和AOT编译.JIT和AOT编译在获取与组件或模块关联的元数据方面有所不同:
// the view compiler needs this data
@Component({
providers: ...
template: ...
})
// the provider compiler needs this data
@NgModule({
providers: ...
});
Run Code Online (Sandbox Code Playgroud)
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 {}
Run Code Online (Sandbox Code Playgroud)
同样,JIT和AOT编译器主要是包装器,用于提取与组件或模块关联的元数据,并且它们都使用底层视图和提供程序编译器来生成工厂.
如果我在使用Webpack和grunt构建它时编译它并部署那个缩小的javascript,AOT和JIT是如何进入图片的?
Angular提供了webpack插件,可以在构建期间从typescript执行转换.这个插件也可以AOT编译你的项目,这样你就不会将JIT编译器包含在bundle中,也不会在客户端上执行编译.
yur*_*zui 18
首先,角度正在远离JIT编译.我希望我们能看到它angular@5.x.x
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
Run Code Online (Sandbox Code Playgroud)
并分析它.然后它需要模板和样式表并解析它.编译器经历了许多我不会在这里描述的步骤.您可以查看描述编译过程的以下页面.Tobias Bosch 也有很多话题.最后编译器创建ngfactories来实例化我们的应用程序.
我认为AIT在JIT中的主要区别在于
ngfactory这个编译器产生的格式是什么在每个页面加载时在我们的浏览器中在客户端运行.
它通过使用收集的元数据ReflectionCapabilities API的@angular/core封装.我们有以下选项在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'
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以在ES5中编写类似的代码.JIT编译器将读取annotations和propMetadata静态属性.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'
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码通常由某些库生成.Angular包也具有相同的格式.这也不适用于aot.我们必须metadata.json用我们的库发送文件进行AOT编译.
3)通过调用装饰器获取元数据
@Component({
selector: 'my-app',
templateUrl: `./app.component.html`
})
export class AppComponent {
@HostBinding('title') test = 'Some title';
}
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
此代码在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;
};
Run Code Online (Sandbox Code Playgroud)
今天它不再使用Reflect api了.编译器直接从__annotations__属性读取数据
if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
return (typeOrFunc as any)[ANNOTATIONS];
}
Run Code Online (Sandbox Code Playgroud)
JIT编译器生成javascript ngfactories
通过使用在构建时在服务器端(nodejs)上运行ngc.
使用AOT,没有运行时编译步骤.当我们在浏览器中运行我们的应用程序时,我们已经预编译了ngfactories.它首先为我们提供了更好的性能和延迟负载.我们也不再@angular/compiler在生产包中提供代码.但是由于我们的ngfactories代码,我们的捆绑包可以显着增长
AOT编译器使用typescript api来分析typescript代码.要获取元数据,编译器将通过StaticSymbolResolver和MetadataCollector API.
因此它需要app.component.ts文件并创建打字稿对象模型.所以我们的AppComponent类会像NodeObjecttype 229(ClassDeclaration)一样呈现
我们可以看到这个对象有decorators属性
由angular团队编写的特殊打字稿包装器,并且被称为tsc-wrapper 努力提取这些元数据.
当编译器遇到d.ts文件时,它试图从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)];
}
}
Run Code Online (Sandbox Code Playgroud)
最后AOT编译器使用TypeScriptEmitter以产生打字稿ngfactories(角<4.4.0)
也可以看看
浏览器加载应用程序包后,Angular 编译器(打包在vendor.bundle.js 内)执行 main.bundle.js 中模板的编译。这称为即时编译。该术语意味着编译是在包到达浏览器时发生的。
JIT编译的缺点是:
加载包和渲染 UI 之间存在时间间隔。这个时间花在JiT编译上。在小型应用程序中,这个时间很少,但在较大的应用程序中,JiT 编译可能需要几秒钟,因此用户需要等待更长的时间才能看到您的应用程序。
Angular 编译器必须包含在vendor.bundle.js 中,这会增加应用程序的大小。
不鼓励在产品中使用 JiT 编译,我们希望在创建包之前将模板预编译为 JavaScript。这就是提前 (AoT) 编译的意义所在。
AoT编译的优点是:
应用程序加载后,浏览器即可呈现 UI。无需等待代码编译。
ngc 编译器不包含在vendor.bundle.js 中,因此您的应用程序的最终大小可能会更小。
如果您使用 Webpack,要执行 AoT,您需要调用 ngc 编译器。例如:
"build:aot": "ngc -p tsconfig.json && webpack --config webpack.config.js"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9712 次 |
| 最近记录: |