В чем разница между Angular AOT и JIT-компилятором
Я погружаюсь в угловой 4, и я пытаюсь понять сборник. Я читал, что AOT и JIT компилируют TypeScript в JavaScript, будь то на стороне сервера или на стороне клиента. Если я собираю его, когда собираю его с помощью Webpack, хрюкаю и внедряю этот минимизированный javascript, как AOT и JIT вообще попадают в картину?
3 ответа
Я читал, что AOT и JIT компилируют TypeScript в JavaScript, будь то на стороне сервера или на стороне клиента.
Нет, это не то, что делают компиляторы AOT и JIT. TypeScript транслируется в JavaScript с помощью компилятора машинописи.
Угловой компилятор
Есть два компилятора, которые выполняют тяжелую работу по компиляции и генерации кода:
Компилятор представлений компилирует шаблоны компонентов и генерирует фабрики представлений. Он анализирует выражения и элементы html внутри шаблона и проходит через многие стандартные фазы компилятора:
parse-tree (lexer) -> abstract-syntax-tree (parser) -> intermediate-code-tree -> output
Компилятор провайдера компилирует провайдеры модулей и генерирует фабрики модулей.
JIT против 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 использует статический анализ кода, предоставляемый компилятором машинописи, для извлечения метаданных и не полагается на оценку кода. Следовательно, он немного ограничен по сравнению с 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, хрюкаю и внедряю этот минимизированный javascript, как AOT и JIT вообще попадают в картину?
Angular предоставляет плагин webpack, который выполняет перенос из машинописного текста во время сборки. Этот плагин также может AOT компилировать ваш проект, чтобы вы не включали JIT-компилятор в комплект и не выполняли компиляцию на клиенте.
Прежде всего, angular отходит от компиляции JIT. Я надеюсь, что мы увидим это в angular@5.x.x
Угловой компилятор принимает все метаданные, которые вы пишете, используя декораторы, такие как
@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
и анализирует это. Затем он берет шаблон и таблицы стилей и анализирует его. Компилятор проходит через много шагов, которые я не буду здесь описывать. Вы можете взглянуть на следующую страницу, которая описывает процесс компиляции. От Тобиаса Босха также много разговоров. Наконец, компилятор создает ngfactories для создания экземпляра нашего приложения.
Я думаю, что основные различия между AOT в JIT
- когда и где выполняется угловая компиляция
- как компилятор собирает метаданные
- какой формат
ngfactory
этот компилятор производит
JIT-компилятор
запускается на стороне клиента в нашем браузере при каждой загрузке страницы.
Он собирает метаданные с помощью API ReflectionCapabilities из @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'
}
}
Подобный код мы можем написать в ES5. JIT-компилятор прочтет annotations
а также propMetadata
статические свойства Компилятор AOT не будет работать с ним.
2) Цикл 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'
}
}
Код выше обычно генерируется некоторой библиотекой. Угловая упаковка также имеет такой же формат. Это также не будет работать с 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-компилятор
работает на стороне сервера (nodejs) во время сборки, используя ngc
,
С AOT нет этапа компиляции во время выполнения. Когда мы запускаем наше приложение в браузере, мы уже предварительно скомпилировали ngfactories
, Это дает нам лучшую производительность вначале и ленивую нагрузку. Мы также не грузим @angular/compiler
код в нашей рабочей комплектации больше. Но наш пакет может значительно вырасти из-за нашего ngfactories
код.
Компилятор AOT использует API- интерфейс машинописи для анализа машинописного кода. Чтобы получить метаданные, компилятор проходит через API-интерфейсы StaticSymbolResolver и MetadataCollector.
Так что требуется app.component.ts
файл и создает машинописную объектную модель. Так что наши AppComponent
класс будет представлен как NodeObject
с типом 229
(ClassDeclaration
)
как мы видим, этот объект имеет decorators
имущество
и специальная машинописная оболочка, написанная угловой командой и называемая 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)];
}
}
И, наконец, компилятор AOT использует TypeScriptEmitter для создания надписей ngfactories (angular <4.4.0)
Смотрите также
После того как браузер загрузит ваши приложения, Angular-компилятор (упакованный в vendor.bundle.js) выполняет компиляцию шаблонов из main.bundle.js. Это называется сборкой Just-in-Time. Этот термин означает, что компиляция происходит во время поступления пакетов в браузер.
Недостатки компиляции JIT:
Существует промежуток времени между загрузкой пакетов и рендерингом пользовательского интерфейса. Это время уходит на сборку JiT. В небольшом приложении это время минимально, но в более крупных приложениях JiT-компиляция может занять пару секунд, поэтому пользователю нужно подождать дольше, чтобы просто увидеть ваше приложение.
Компилятор Angular должен быть включен в vendor.bundle.js, который увеличивает размер вашего приложения.
Использование JiT-компиляции в prod не рекомендуется, и мы хотим, чтобы шаблоны были предварительно скомпилированы в JavaScript перед созданием пакетов. Это то, что представляет собой компиляция Ahead-of-Time (AoT).
Преимущества компиляции AoT:
Браузер может отображать пользовательский интерфейс сразу после загрузки приложения. Нет необходимости ждать компиляции кода.
Компилятор ngc не включен в vendor.bundle.js, и результирующий размер вашего приложения может быть меньше.
Если вы используете Webpack, для выполнения AoT вам нужно вызвать компилятор ngc. Например:
"build:aot": "ngc -p tsconfig.json && webpack --config webpack.config.js"