Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS performance with many directives

I'm using AngularJS 1.0.8.

The problem: I have a dynamic website that can be built from various components, or widgets: paragraphs, text blocks, images, hyperlinks, and tables, for that matter. A paragraph is a container of more components. A table is also a kind of a container - it can hold other components, and it arranges them as a datagrid.

The website is not static, i.e. I don't have a pre-defined layout of such components. Instead, I get a JSON in startup, that specifies the layout of the components.

Originally, I had a directive of each such component, using templates for that directives, and occasionally using $compile to change the DOM a bit for more complex components. For the 'container' components - paragraphs and tables - I used ngRepeat to render all of the components that are contained in that container-component.

That was problematic performance-wise. It would take the website many seconds to load on Chrome/Firefox, with the time spent mainly in the AngularJS render mechanism (not in IO, I figured).

So I decided to change the directives of these components. Instead of using ngRepeat, which is not really necessary since I don't need the two-way binding (the content in the website is not interactive and cannot be changed, so really I only need to render it once, very much like a servlet) - I built the HTML string in the directive myself, using plain JS, iterating over all of the contained components that exist in the model, and at the end I $compiled and linked it.

The result wasn't good enough again. For a table of a few hundered cells, it took ~500 milis to link in modern Chrome/Firefox, and ~4000 milis in IE9, and ~15000 milis in IE8, and IE7 is still rendering so I can't give you the time :)

I thought that the problem might be with an extensive use of directives.
A simple:

<div my-table-component data="data"></div>

element would result, after the link, in a <table> tag with 30-40 <tr> tags, each with 10 <td> tags, and in each there would be an additional <div my-text-component> or <div my-image-component> that would then have to be compiled and linked by itself (since it has a directive).

I though that since my website is not interactive to begin with, I don't really need this. Maybe I could avoid using directives for each component, and leave only a directive for the container-components. In these directives, I would create the actual HTML template of every possible other component, instead of using directives that would do that.

That takes me another step away from the AngularJS idea towards a servlet idea. And it kind of sucks. So maybe one of you can offer a better approach for me... Maybe the performance problem is not even there? Maybe a use of directives (and hopefully ngRepeat) can be fine performance-wise even with this amount of items? Maybe there's a better way to make an insightful performance benchmark, other than using Chrome's Developer Tools, Firebug, and Chrome's Batarang AngularJS extension (none of them really directed me in a productive way).

like image 730
Daniel Wolf Avatar asked Sep 08 '13 13:09

Daniel Wolf


Video Answer


1 Answers

Using a lot of nested directives by itself is not a problem, but any extensive binding could have huge impacts.

If someone is still looking for an aswer to this, using Angular 1.3+, OP could solve his problem by first using one-time binding on all the elements on which he says there is "no need for two-ways bindings", using the ::binding syntax.

In addition, I would suggest trying to spot which bindings exactly are being particularly slow, using the amazing profiling snippets from this website: http://bahmutov.calepin.co/improving-angular-web-app-performance-example.html

Finally, what often takes most time in Angular, especially while building big ng-repeated tables, is the compilation phase. So if possible try to only build a restricted number of elements (using limitTo) and then load more as the user scrolls for instance. Many directives address this concern (look for "infinite scrolling")

All in all, I think it is still worth trying to optimize an Angular application rather tham switching to native JS, most of the time the lag comes from a developper mistake: some applications have thousands of watchers and run pretty smoothly (*cough* like mine *cough*).

like image 96
floribon Avatar answered Nov 15 '22 07:11

floribon