source: https://www.techadvisor.co.uk/how-to/broadband/test-internet-speed-3521885/

Some things I wish I knew before I start to work with Angular. Part 2. (Performance)

piotr szybicki
12 developer labors
7 min readNov 23, 2018

--

Link to part 1.

A while ago I wrote a article about HTTP Caching and how to make our app load faster.

This one will be set in the world of performance. We will focus on performance of the code in the angular. And some coding styles that can help us write more user friendly application. As well as write more maintainable code. Because, whether intentionally or not, taking performance in to account make it also more readable.

Change Detection, understand it.

Change detection. A mysterious beast that abstracts away the re rendering of component whenever we update our model. I will not try to explain the entire process as the article from angular university does great job.

But basically every component has it’s own change detector and it can be set to Default or OnPush. Default means that when change detection is triggered the properties of the model (all the bindings [someObject]=”object” ) are compared property by property (this is quite slow). You have to know that change detection pass can be executed hundred’s of times a second.

Let’s say you bind an object with 100 fields to be displayed in a child component wouldn't it be better if you can just oldObject === newObject. Quick reference check is way faster. And this is exactly what OnPush does. I strongly encourage to set this property on all your components. Because it demand from the developer to fallow the concept they should be following anyway:

Immutability

The backend developers got clever some time ago and said ‘from now on our apps will be stateless’. This was very clever on their part as a lot of bugs want away but that complexity has to go somewhere (there is no free lunch). Some of it want to DB but most of it was put to the front. And suddenly the same bugs that java developers had to deal with start poping up in work of Angular, React, Vue.js developers. Decent way to attack the problem for the backend developers was to create immutable data-structures with immutable objects in them. So Facebook engineers, clever beast they are, create a library called Immutable.js that helps you do exactly that but in java script.

You see I lie to you a little bit earlier when i said that state, and state mutation is bad. Hidden state mutation is bad. As it makes harder to track the changes to an object in your application. Immutability is not really about removing state it is about making state changes more explicit. Immutable.js helps us to achieve exactly that. By creating collections, objects that can’t change. the only way is to go from state 1 -> state 2 is to recreate original object with new properties.

That also means that the address in memory, reference adders will change. And that we are going back the full circle. Remember when I told you the onPush does quick reference check :) that is why using immutalbe.js is so advantageous.

So how we can use it. Well we have collections and the elements in those collections and depending on your use case you might need to make them both immutable.

This is how you work with the simple object, in my case it is a very simple address object. There is a lot of boilerplate involved but this is the price we pay. But to quote a scene from one of my favorites movies ‘Equilibrium’: “Havy cost, I pay it gladly”. To be honest it is a little bit of hack that we have to use as there is nothing baked in to a language it’s self that would allow us to protect the access.

There is a world read-only in typescript spec but let’t be honest without a run-time check it is pretty useless. As I demonstrate it in the above example (line 27).

Fortunately we don’t have to play around with the collections that much. And to be honest we need it far more than the immutable objects. Especially that more often then not we pass observable to the component rather then bind the object itself. But we will deal with that later. So back to collections. Aside a few exceptions (and you will find them pretty fast if you depend on a behavior like pop) they work just like the collection native to javascript.

As you can see there are no difference. I encourage you to take a look at the documentation it is well written and with many examples.

Usage of trackBy

Of course we can’t talk about the collection and not talk about this little guy. Because let’s say we have a following scenario. We have a list of 100 elements. And we are not paging it. Everything gets displayed at once. And now assume that we have to add one list to that element (BTW immutable.js has nothing to do with this, the same can be expected when using native collections) Then if we are using structural directive *ngFor:

<ul>
<li *ngFor="let hr of heroes">{{hr.name}}</li>
</ul>

All elements will be re-rendered. Angular just has no way of knowing which has changed. There is no notion of identity. And we have to provide it. Using cool function called trackedBy.

<ul>
<li *ngFor="let hr of heroes;trackBy: trackByFn">{{hr.name}}</li>
</ul>

And then in component:

trackByFn(index, item) {    
return item.id
}

It will course only a inserted element to be re-rendered. And if we delete the element the browser rendered will not be triggered. Very nice blog post:

Pure pipes

OK, So we covered some cases where using property binding with onPush strategy can help us. But it is not always enough. You see i keep important information for the patient ones :). It is not only when the reference binding changes angular trigger the change detection. It is also when the event is fired from the component. And the behavior is the same both for custom and the javascript events(the one that bubble). And that is a good thing, there is no way of knowing if our event make some changes in that component (it could do that without changing bindings).

Lets take a look at the above code. We have a list of components (that display movie titles, as buttons) and when user clicks on the button it removes it form the list and consequently from the page.

In lines there are 3 possible implementations of this component (line: 9, 12, 15). Les’t say that we have businesses requirement to make all the titles uppercase ( stupid but it’t to illustrate a point). We have 3 options to make it happen. Function(line 9), Pipe(line 15) or modify the value before we pass it to the component (line 12).

The solution where we modify the value before it is bind is pretty ridged. It prevents re-usability of the data, plus it moves part of the display logic that belongs to this component outside of it. Not a good idea. Although there is no performance hit that I will be talking about in the next paragraph.

So it is between the pipe and function. But there is a problem. I told you that angular uses a reference check, so when the change detection pass gets to our movie component it has to re-run the function to obtain that reference. No imagine that you actually run more complex logic inside of that function or call backend for some additional data. No to mention that almost always the function will return object that will be in new location in memory thus re-rendering the component. The solution to that are pipes, more concretely pure pipes.

By default all pipes in angular are considered pure. So the line 3 in code above is not necessary. Angular can do all sorts of optimizations on when pure pipes are used. One it create a single instance of that pipe and shares it among components, second it can cache the input, output relationship and when the same input is passed angular will not recalculate the output.

Further reading:

Observable result caching and sharing

This might be of limited use, but there ware couple of use cases in the past where I found it useful. In my case I was pulling a lot of data from the backend but the data have never changed. It was either a dictionary of some sort or list of items that I didn’t need to pull every time. Normally when you subscribe to regular observable all methods will be executed from the beginning (remember observable are just methods, well to be technical they are IO monads, I like to split hairs). And this might not always be what you need.

I found that making the observable into a shared, or connectable observable and buffering the output solves the issue.

In the above example we subscribe to observable twice but http.get will be called only once because publishReplay(1), refCount().

--

--

piotr szybicki
12 developer labors

Piotr Szybicki’s, Programmer, Java Developer, ML Entusiast