Angular Slowness Reasons and Remedies

JS
R
JavaScript

Collection of hints and advice from AngularConnect and blogs in order to attack slowness on Angular apps. *non-curated yet

1- Too much Rendering: update only onPush; use TrackBy for arrays
2- Observables emitting too much: use filter and distinctUntilChanged to prevent emitting
3- High Frequency Updates (for each DomEvent or WS, Zone will trigger a change detection): ngZone.runOutsideAngular
4- Long Lists: keying (assign a key to each item of a list, the library will only re-render if the key has changed)
5- VirtualScrolling (only render what user can see): Angular CDK 
6https://material.angular.io/cdk/scrolling/overview
7- Async Rendering: render 50 items out of 500; then scheduled following items using setTimeout(0)
8- Lazy Rendering: show a dummy render, and then instantiate the component when the user moves mouse hover
9- Lazy Listeners: Subscribe only to visible items (Virtual Scrolling)
10- Too many listeners: Use less channels and try to use exisiting ones
11- WebWorkers for heavy processing: https://angular.io/guide/web-worker
12- Angular Built-in optimisers: Custom Iterable Differ
13https://blog.mgechev.com/2017/11/14/angular-iterablediffer-keyvaluediffer-custom-differ-track-by-fn-performance/
14- Looping: for loop is faster than filter / reduce/ map (use also break and continue)
15
16Categorisation of Components
17// Critical (List)
18- List
19- Tree
20- Select
21
22// Critical (repeated, go into list)
23- Icon
24- Button
25- Menu
26
27// Non Critical
28- Date Pickers
29- Dialogs
30- Isolated components
31
3233AVOID:
34cd.detectChanges(); // synchronous will block UI Thread — freeze page
35
36USE:
37cd.markForCheck(); // together with onPush — waits for next tick
38
3940AVOID:
41[ngClass]=“‘foo’”
42
43USE:
44class=‘foo’
45
4647AVOID:
48[ngStyle]={color: ‘red’}49
50USER:
51[style.color]=“’red’”
52
5354AVOID:
55<*ngFor=let item of items”>
56<ng-container *ngTemplateOutlet=“itemTemplate”/>
57<ngTemplate #itemTemplate>
58</ngTemplate>
59
60USE:
61<!Template outside of ngFor —>
62<div *ngFor=let item of items”>
63<ng-container>
64*ngTemplateOutlet=“itemTemplate”> 
65<ng-container>
66</div>
67
68<ng-template #itemTemplate>
69Xxx
70</ng-template>
71
7273AVOID:
74allRows.subscribe();
75
76USE:
77visibleRows.subscribe();
78
7980AVOID:
81@Component({
82    Selector: ‘cell’
83})
84
85Export class DomCell {}
86
87USE:
88@Directive({
89	selector:[cell]90});
91
92Export class DirctvPerCell {}
93
9495AVOID (1 listener per event type):
96@Directive({
97selector: ‘tooltip’,
98Host: {‘mouseover’: ’show()}
99})
100
101USE:
102@Injectable({providedIn: ‘root’})
103Export Class Tooltip {
104	constructor() {
105		document.addEventListener(mouseover);
106	}
107}
108
109110AVOID
111// Layout trashing within list (cell in table)
112@Directive({
113Selector:[cell]114)}
115Export DirecttiveCellTable {
116	ngAfterViewInit() {
117		element.classList.add(‘foo’);
118		const foo = element.offSetheight;
119	}
120}
121
122USE:
123fastdom.measure(() => {
124	foo = element.offSetHeight;
125});
126
127AVOID
128<table>
129	<tr *ngFor=let I of items”>
130		<td>
131			<mat-dialog> **has lot of default bindings
132		</td>
133	</tr>
134</table>
135
136
137USE:
138<table>
139	<tr *ngFor=let I of items”>
140		<td>
141			<mat-dialog-wrapper>
142		</td>
143	</tr>
144</table>
145
146
147148AVOID:
149Promise.resolve()
150setTimeout()
151setInterval()
152*all of this are monkey patched by Zone, it will run change detection
153
154USE:
155this.ngZone.runOutsideAngular(
156(()=>{
157	setTimeout()
158	}
159}
160
161162AVOID:
163@Directive({
164	seletor: ‘tooltip’,
165	host: { ‘mousewheel’: ‘foo()}
166});
167Expire class ActiveListeners {
168	foo() {}
169}
170
171USE:
172Passive Event Listener
173
174@Directive({
175	seletor: ‘tooltip’,
176});
177Expire class ActiveListeners {
178	constructor() {
179	document.addEventListener(‘touchstart’, () => {}, {passive: true});
180	}
181}
182
183
184185AVOID:
186opacity: 0;
187
188USE:
189Visibility: hidden; // chrome doesn’t draw nothing
190
191
192193AVOID
194Letter-spacing: $non-zero-value;
195
196USE:
197Letter-spacing: 0;
198
199
200
201
202
203
204ngClass / ngFloor (iterableDiffers: compares 2 arrays, checks it’s has been added or removed, indexes changed)
205
206
207

Created on 2/9/2020