slides: bit.ly/jsheroes-ivy
Frontend Developer
organizer for ngBucharest
@ngBucharest
groups/angularjs.bucharest
8 - 9 October 2020, Timisoara
@Injectable({
providedIn: "root" | "any" | "platform"
})
export class MyService {}
ng update @angular/core @angular/cli
Angular templates (declarative)
JavaScript code that runs in the browser
compilation
@Component({
selector: ‘app-component’
template:
'<h1>{{ title }}</h1>'
})
export class AppCmp {
title = "hello";
}
export class AppCmp {
title: string;
ngComponentDef
= ng.defineComponent({...})
}
ngc
Angular Compiler
Angular Runtime
(not shipped with your final bundle when using AOT)
app.component.ts
app.component.html
app.component.(s)css
app.component.js
app.component.ngfactory.js
app.component.metadata.json
app.component.ngsummary.json
// moduleA.js
export function f1() {
...
}
export function f2() {
...
}
// main.js
import { f1 } from './moduleA.js';
f1();
Only f1 is included in the final bundle
// moduleA.js
export function f1() {
...
}
export function f2() {
...
}
// main.js
import { f1 } from './moduleA.js';
f1();
if(condition) {
f2();
}
Both f1 and f2 are included in the bundle
app.component.ts
app.component.html
app.component.(s)css
app.component.js
No more ngfactory files!
@Component({
selector: 'app',
template: `<h1>{{title}}</h1>`
})
class AppComponent {
title="Ivy Renderer";
}
var AppComponent = (function () {
AppComponent.ngComponentDef = defineComponent({
type: AppComponent,
selectors: [["app-root"]],
consts: 2,
vars: 1,
template: function AppComponent_Template(renderFlags, ctx) {
if (renderFlags & RenderFlags.Create) {
elementStart(0, "h1");
text(1);
elementEnd();
} if (renderFlags & RenderFlags.Update) {
textBinding(1, interpolation1("", ctx.title, ""));
}
},
encapsulation: 2
});
}());
creation phase
update/change phase
AppComponent.ngComponentDef.template(create, app)
AppComponent
UserComponent
WidgetComponent
AppComponent.ngComponentDef.template(create, app)
UserComponent.ngComponentDef.template(create, user)
WidtgetComponent.ngComponentDef.template(create, widget)
element()
text()
template()
elementContainer()
projection()
listener()
pipe()
i18n()
...
property()
attribute()
styleProp()
classProp()
hostProperty()
pipeBind()
textInterpolate1-8()
pureFunction1-8()
...
Angular
export function elementStart() { ... } export function text() { ... } export function attribute() { ... }
elementStart() text() attribute()
// other unused Angular features -> tree-shaken
...
<div>
<span>{{title}}</span>
<child-component *ngIf="show"></child-component>
</div>
function View_RootCmp_0(_l) {
return ng.ɵvid(0, [
(_l()(), ng.ɵeld(0, 0, null, null, 4, "div", [], null, null, null, null, null)),
(_l()(), ng.ɵeld(1, 0, null, null, 1, "span", [], null, null, null, null, null)),
(_l()(), ng.ɵted(2, null, ["", ""])),
(_l()(), ng.ɵand(16777216, null, null, 1, null, View_RootCmp_1)),
ng.ɵdid(4, 16384, null, 0, ng.NgIf, [ng.ViewContainerRef, ng.TemplateRef], {ngIf: [0, "ngIf"]}, null)
], );
}
ViewEngine - non-locality
<div>
<span>{{title}}</span>
<child-component *ngIf="show"></child-component>
</div>
function RootCmp_Template(rf, ctx) {
if (rf & 1) {
ng.ɵelementStart(0, "div");
ng.ɵelementStart(1, "span");
ng.ɵtext(2);
ng.ɵelementEnd();
ng.ɵtemplate(3, RootCmp_child_cmp_Template_3, 1, 0, null, [1, "ngIf"]);
ng.ɵelementEnd();
} if (rf & 2) {
ng.ɵtextBinding(2, ng.ɵinterpolation1("",
ctx.title, ""));
ng.ɵelementProperty(3, "ngIf", ng.ɵbind(ctx.show));
}
}
Ivy - locality
NgIf.ngDirectiveDef = i0.ɵdefineDirective({
factory: function NgIf_Factory(t) {
return new NgIf(
i0.ɵinject(ViewContainerRef),
i0.ɵinject(TemplateRef)
);
},
...
});
(do try this at home)
branch: 1-render_single_component
branch: 2-moduless-component-and-zoneless-change-detection
branch: 3-lazy-load-components
branch: 4-higher-order-components