Writing Robust AngularJS Web Applications
Consider the size of expressions being watched
Even if we manage to avoid deep-watches we should still try to think about an
exact value being watched and compared by AngularJS. This is not always obvious,
especially with watches registered by AngularJS while processing templates.
See the following example of a longer text with one AngularJS expression inside:
<p>This is very long text that refers to one {{variable}} defined on a
scope. This text can be really, really long and occupy a lot of space
in memory. It is so long since... </p>
You would probably expect that AngularJS, while processing this template, will
create a watch where the watch expression is equal to variable. Unfortunately, this
is not the case; the whole text enclosed by
tags will be used. This means that the
whole, potentially long text will be copied and stored in memory. We can limit the
size of this expression by introducing a tag to delimit part of the text that
should be data-bound:
<p>This is very long text that refers to one <span ng-
bind='variable'></span> defined on a scope. This text can be really,
really long and occupy a lot of space in memory. It is so long since...
</p>
After this simple change AngularJS will register a watcher where the watch
expression consists of the variable only.
The ng-repeat directive
The ng-repeat directive would probably win a contest for the most useful directive,
if one could be organized. It has enormous power coupled with very simple syntax.
Unfortunately, ng-repeat is also one of the most performance-sensitive directives.
There are two reasons for this. Firstly it needs to do nontrivial inspection of a collection
in each turn of the $digest loop. Then, when changes are detected, impacted DOM
elements need to be reshuffled which may result in many DOM operations.
Collection watching in ng-repeat
The ng-repeat directive needs to keep track of changes to the collection it iterates
over. To operate properly the directive needs to be able to identify elements that
were added to a collection, moved within a collection or removed entirely. It does so
by executing a nontrivial algorithm as part of each $digest loop. Without going into
the details of this algorithm, its performance is linked to the size of a collection.