Angular Slowness Reasons and Remedies
JS
R
JavaScriptCollection 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
32—
33AVOID:
34cd.detectChanges(); // synchronous will block UI Thread — freeze page
35
36USE:
37cd.markForCheck(); // together with onPush — waits for next tick
38
39—
40AVOID:
41[ngClass]=“‘foo’”
42
43USE:
44class=‘foo’
45
46—
47AVOID:
48[ngStyle]=“{color: ‘red’}”
49
50USER:
51[style.color]=“’red’”
52
53—
54AVOID:
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
72—
73AVOID:
74allRows.subscribe();
75
76USE:
77visibleRows.subscribe();
78
79—
80AVOID:
81@Component({
82 Selector: ‘cell’
83})
84
85Export class DomCell {}
86
87USE:
88@Directive({
89 selector: ‘[cell]’
90});
91
92Export class DirctvPerCell {}
93
94—
95AVOID (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
109—
110AVOID
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
147—
148AVOID:
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
161—
162AVOID:
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
184—
185AVOID:
186opacity: 0;
187
188USE:
189Visibility: hidden; // chrome doesn’t draw nothing
190
191
192—
193AVOID
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
207Created on 2/9/2020