Replace
ChangeDetectorRef.detectChanges() with ChangeDetectorRef.markForCheck()
Reason: Synchronous blocks rendering violates parent -> child data flow. Can’t be batched
2. IterableDiffers
Unnecessary CPU/Memory Usage
Replace
[ngClass]=”’foo’” withclass=”foo”
Replace
[ngStyle]=”{color='red'}” with {style.color]="red"
Replace
*ngFor="let item of items" with *ngFor=(const item of items)
7
Replace
<div *ngFor="let item of items">
<ng-container *ngTemplateOutlet="itemTemplate"/>
<ng-template #itemTemplate">foo</ng-template>
</div>with<div *ngFor="let item of items">
<ng-container *ngTemplateOutlet="itemTemplate"/>
</div>
<ng-template #itemTemplate">foo</ng-template>
Reason: Angular initializes ng-template per item and unnecessary CPU utilization.
8.
Replace
@Directive({ selector:'tooltip'}, host:{'mouseover':show()} })
export class Tooltip{}with@Injectable({ provideIn:'root'} })
export class Tooltip{
constructor(){
document.addEventListener(mouseover)
}
}
9. Replace
@Directive({selector:’[cell]’})
export class DirecvPerCellInTable{
ngAfterViewInit() {
element.classList.add(‘foo’);
const foo = element.offsetHeight;
}
}with
Fastdom.measure(()=>{foo=element.offsetHeight;})
Reason: Chrome has to recalculate the layout to come up with answer
Benchmarks showed 80% drop in renderTime
10. Replace
<table>
<tr *ngFor=”let item of items”>
<td>mat-checkbox></mat-checkbox></td>
</tr>
</table>with<table>
<tr *ngFor=”let item of items”>
<td><mat-pseudo-checkbox></mat-pseudo-checkbox></td>
</tr>
</table>
Reason: Less Angular binding
Less DOM
Don’t forget to add back aria roles
DOM for mat-checkbox is heavy
Benchmarks showed 8% drop in renderTime
11. Replace
promise.resolve(foo)
setInterval(foo)function foo() {el.classList.add(‘foo’); }withthis.ngZone.runOutsideAngular(()={setTimeout(foo);})
Reason: Angular wraps setTimeout, to execute change detection. You don’t need Angular CD
12. Replace
@Directive({selector:’[cell]’})
export class DirctvPerCellInTable{
ngAfterViewInit() {
setTimeout(()=>{…}
)
}
}with @CompositionEvent({selector: ‘table’})
export class Table{
ngAfterViewInit() {
setTimeout(()=>{…}
)
}
Reason: After each setTimeout Angular executes changes detection.
Batching setTimeout has increased performance 56%
13. Replace
@Directive({selector:’tooltip’, host: {‘mousewheel’:’foo()’},})
export class ActiveListeners{foo(){…}}with
@Directive({selector:’tooltip’})export class ActiveListeners{constructor(){document.addEventListener(‘touchstart’,()={…}, {passive: true})}}
Reason: Chrome blocks rendering if the listener is not passive!
Angular doesn’t support this yet
14. Replace .show-on-hover{opacity: 0;}
.show-on-:hovered{opacity: 1;}
with .show-on-hover{opacity: 0;}
.show-on-:hovered{opacity: 1; will-change: opacity;}
Reason: Potential layout thrashing.
15. Replace
opacity: 0;with visibility: hidden;
Reason: Inefficient painting in Chrome
16. Replace letter-spacing: letter-spacing: 0;
with $non-zero-value
Reason: letter-spacing causes post processing in Chrome
Benchmarks have showed 15% improvement in renderTime.