Overview
Ivy is a new backwards-compatible Angular renderer focused on further speed improvements, size reduction, and increased flexibility.
Ivy is currently not feature complete, but can be tested via enableIvy: true angularCompilerOptions flag.
We currently expect Ivy to remain behind the flag until it's feature complete and battle tested at Google. In the meantime you can check out this Hello World demo.
Implementation Status
The work can be divided into three categories:
@angular/compiler-cli: TypeScript transformer pipeline which includes two command line tools:
ngtsc: (Angular TypeScript Compiler) Angular compiler which strips out @Component (and friends) and replaces it with defineComponent (and friends).
ngcc: (Angular Compatibility Compiler) NPM upgrade compiler which reads the .STORING_METADATA_IN_D.TS.json files and .js files and adds defineComponent (and friends) into the node_module. This in effect converts a pre-ivy module into ivy module.
@angular/compiler: Ivy Compiler which converts decorator into ivy
@angular/core: Decorators which can be patched with @angular/compiler.
@angular/compiler-cli changes
ngtsc TSC compiler transformer
TSC transformer which removes and converts @Pipe, @Component, @Directive and @NgModule
to the corresponding definePipe, defineComponent, defineDirective and defineInjector.
- ❌ Basic setup of the transformer into
tsc
- ❌ Can read STORING_METADATA_IN_D.TS from
.d.ts (see: STORING_METADATA_IN_D.TS.md)
- ❌ Detect decorators and convert them to the
defineXXX method using the __Compiler in @angular/compiler.
- ❌
@Pipe => definePipe
- ❌
@Component => defineComponent
- ❌
@Directive => defineDirective
- ❌
@NgModule => defineInjector
- ❌ Encode selectors into
.d.ts file.
- ❌ support
extends for @Pipe, @Component, @Directive and @NgModule.
- ❌ Documentation
ngcc Angular node_module compatibility compiler
A tool which "upgrades" node_module compiled with non-ivy ngc into ivy compliant format.
- ❌ Basic setup of stand alone executable
- ❌ Integration with WebPack (cli)
- ❌ Rewrite existing code by interpreting the associated STORING_METADATA_IN_D.TS
- ❌
PipeCompiler: @Pipe => definePipe
- ❌
DirectiveCompiler: @Directive => defineDirective
- ❌
NgModuleCompiler: @NgModule => defineInjector
- ❌
ComponentCompiler: @Component => defineComponent
- ❌
TemplateCompiler
- ❌
StyleCompiler
- ❌ Documentation
@angular/compiler changes
- ❌ Component compilation: Translates
@Component => defineComponent
- ❌
TemplateCompiler (current known as ViewCompiler)
- ❌
StyleCompiler
- ❌
PipeCompiler: Translates @Pipe => definePipe
- ❌
DirectiveCompiler: Translates @Directive => defineDirective
- ❌
InjectableCompiler: Translates @Injectable => defineInjectable
- ❌
NgModuleCompiler: Translates @NgModule => defineInjector (and defineNgModule only in jit)
- ❌ Documentation
@angular/core changes
The goal is for the @Component (and friends) to be the compiler of template. Since decorators are functions which execute during parsing of the .js file, the decorator can compile the template into Ivy. The AoT compiler's job is to remove the @Component and replace it with call to defineComponent.
- ❌ Remove
createDecorator (and friends) since we no longer support other modes.
- ❌
@angular/compiler can patch itself onto:
- ❌
@Injectable
- ❌
@NgModule
- ❌
@Pipe
- ❌
@Directive
- ❌
@Component
- ❌
ResourceLoader.resolved: Promise<> Returns true if all templateUrls and styleUrl have been resolved and application is ready to be bootstrapped.
Crosscutting
Decorators
| Annotation |
defineXXX() |
Run time |
Spec |
Compiler |
Back Patch |
@Component |
✅ defineComponent() |
✅ |
✅ |
✅ |
❌ |
@Directive |
✅ defineDirective() |
✅ |
✅ |
✅ |
❌ |
@Directive |
❌ defineAbstractDirective() |
❌ |
❌ |
❌ |
❌ |
@Pipe |
✅ definePipe() |
✅ |
✅ |
✅ |
❌ |
@Injectable |
✅ defineInjectable() |
✅ |
❌ |
❌ |
❌ |
@NgModule |
✅ defineInjector() |
✅ |
❌ |
❌ |
❌ |
@ConfigureInjector |
❌ defineInjector() |
❌ |
❌ |
❌ |
❌ |
Component Composition
| Feature |
Runtime |
Spec |
Compiler |
| creation reordering based on injection |
❌ |
❌ |
✅ |
class CompA extends CompB {} |
❌ |
❌ |
❌ |
class CompA extends CompB { @Input } |
❌ |
❌ |
❌ |
class CompA extends CompB { @Output } |
❌ |
❌ |
❌ |
Change Detection
| Feature |
Runtime |
markDirty() |
✅ |
detectChanges() |
✅ |
tick() |
✅ |
attach() |
✅ |
detach() |
✅ |
ON_PUSH |
✅ |
ALWAYS |
✅ |
DIRTY |
✅ |
ATTACHED |
✅ |
Bootstrap API
| Feature |
Runtime |
renderComponent() |
✅ |
getHostElement() |
✅ |
createInjector() |
✅ |
Template Compiler
Template Syntax
| Feature |
Runtime |
Spec |
Compiler |
<div> |
✅ |
✅ |
✅ |
<div>{{exp}}</div> |
✅ |
✅ |
✅ |
<div attr=value> |
✅ |
✅ |
✅ |
<div (click)="stmt"> |
✅ |
✅ |
✅ |
<div #foo> |
✅ |
✅ |
✅ |
<div #foo="bar"> |
✅ |
✅ |
✅ |
<div [value]="exp"> |
✅ |
✅ |
✅ |
<div title="Hello {{name}}!"> |
✅ |
✅ |
✅ |
<div [attr.value]="exp"> |
✅ |
✅ |
❌ |
<div class="literal"> |
✅ |
✅ |
✅ |
<div [class]="exp"> |
❌ |
❌ |
❌ |
<div [class.foo]="exp"> |
✅ |
✅ |
❌ |
<div style="literal"> |
✅ |
✅ |
✅ |
<div [style]="exp"> |
❌ |
❌ |
❌ |
<div [style.foo]="exp"> |
✅ |
✅ |
❌ |
{{ ['literal', exp ] }} |
✅ |
✅ |
✅ |
{{ { a: 'literal', b: exp } }} |
✅ |
✅ |
✅ |
{{ exp | pipe: arg }} |
✅ |
✅ |
✅ |
<svg:g svg:p> |
❌ |
❌ |
❌ |
<img src=[userData]> sanitization |
❌ |
❌ |
❌ |
Life Cycle Hooks
| Feature |
Runtime |
Spec |
Compiler |
onChanges() |
✅ |
✅ |
✅ |
onDestroy() |
✅ |
✅ |
✅ |
onInit() |
✅ |
✅ |
✅ |
onChanges() |
✅ |
✅ |
✅ |
doCheck() |
✅ |
✅ |
✅ |
afterViewChecked() |
✅ |
✅ |
✅ |
afterViewInit() |
✅ |
✅ |
✅ |
afterContentChecked() |
✅ |
✅ |
✅ |
afterContentInit() |
✅ |
✅ |
✅ |
| listener teardown |
✅ |
✅ |
✅ |
@Query
| Feature |
Runtime |
Spec |
Compiler |
@Query(descendants) |
✅ |
✅ |
n/a |
@Query(one) |
✅ |
✅ |
n/a |
@Query(read) |
✅ |
✅ |
n/a |
@Query(selector) |
✅ |
✅ |
n/a |
@Query(Type) |
✅ |
✅ |
n/a |
@ContentChildred |
✅ |
✅ |
❌ |
@ContentChild |
✅ |
✅ |
✅ |
@ViewChildren |
✅ |
✅ |
❌ |
@ViewChild |
✅ |
✅ |
✅ |
Content Projection
| Feature |
Runtime |
Spec |
Compiler |
<ng-content> |
✅ |
✅ |
✅ |
<ng-content selector="..."> |
✅ |
✅ |
✅ |
container projectAs |
✅ |
✅ |
❌ |
Injection Features
| Feature |
Runtime |
Spec |
Compiler |
inject(Type) |
✅ |
✅ |
✅ |
directiveInject(Type) |
✅ |
✅ |
❌ |
inject(Type, SkipSelf) |
❌ |
❌ |
❌ |
attribute('name') |
✅ |
✅ |
❌ |
injectChangeDetectionRef() |
✅ |
✅ |
❌ |
injectElementRef() |
✅ |
✅ |
✅ |
injectViewContainerRef() |
✅ |
✅ |
✅ |
injectTemplateRef() |
✅ |
✅ |
✅ |
default inject() with no injector |
❌ |
❌ |
❌ |
| sanitization with no injector |
✅ |
✅ |
❌ |
I18N
| Feature |
Runtime |
Spec |
Compiler |
| translate text literals |
❌ |
❌ |
❌ |
| rearrange text nodes |
❌ |
❌ |
❌ |
| ICU |
❌ |
❌ |
❌ |
View Encapsulation
| Feature |
Runtime |
Spec |
Compiler |
| Render3.None |
✅ |
✅ |
✅ |
| Render2.None |
✅ |
✅ |
✅ |
| Render2.Emulated |
❌ |
❌ |
❌ |
| Render2.Native |
❌ |
❌ |
❌ |
______Refs
| Method |
View Container Ref |
Template Ref |
Embeded View Ref |
View Ref |
Element Ref |
Change Detection Ref |
clear() |
❌ |
n/a |
n/a |
n/a |
n/a |
n/a |
get() |
❌ |
n/a |
n/a |
n/a |
n/a |
n/a |
createEmbededView() |
✅ |
✅ |
n/a |
n/a |
n/a |
n/a |
createComponent() |
✅ |
n/a |
n/a |
n/a |
n/a |
n/a |
insert() |
✅ |
n/a |
n/a |
n/a |
n/a |
n/a |
move() |
❌ |
n/a |
n/a |
n/a |
n/a |
n/a |
indexOf() |
❌ |
n/a |
n/a |
n/a |
n/a |
n/a |
destroy() |
n/a |
n/a |
❌ |
❌ |
n/a |
n/a |
destroyed |
n/a |
n/a |
❌ |
❌ |
n/a |
n/a |
onDestroy() |
n/a |
n/a |
❌ |
❌ |
n/a |
n/a |
markForCheck() |
n/a |
n/a |
❌ |
n/a |
n/a |
✅ |
detach() |
❌ |
n/a |
❌ |
n/a |
n/a |
✅ |
detachChanges() |
n/a |
n/a |
❌ |
n/a |
n/a |
✅ |
checkNoChanges() |
n/a |
n/a |
❌ |
n/a |
n/a |
✅ |
reattach() |
n/a |
n/a |
❌ |
n/a |
n/a |
✅ |
nativeElement() |
n/a |
n/a |
n/a |
n/a |
✅ |
n/a |